/**
 *******************************************************************************
 * Copyright (C) 1996-2010, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
package com.ibm.icu.text;

import java.io.DataInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.text.CharacterIterator;
import java.text.ParseException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Set;

import com.ibm.icu.impl.BOCU;
import com.ibm.icu.impl.ICUDebug;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.ImplicitCEGenerator;
import com.ibm.icu.impl.IntTrie;
import com.ibm.icu.impl.StringUCharacterIterator;
import com.ibm.icu.impl.Trie;
import com.ibm.icu.impl.TrieIterator;
import com.ibm.icu.impl.Utility;
import com.ibm.icu.lang.UCharacter;
import com.ibm.icu.lang.UScript;
import com.ibm.icu.util.RangeValueIterator;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.UResourceBundle;
import com.ibm.icu.util.VersionInfo;

/**
 * <p>
 * RuleBasedCollator is a concrete subclass of Collator. It allows customization of the Collator via user-specified rule
 * sets. RuleBasedCollator is designed to be fully compliant to the <a
 * href="http://www.unicode.org/unicode/reports/tr10/">Unicode Collation Algorithm (UCA)</a> and conforms to ISO 14651.
 * </p>
 * 
 * <p>
 * Users are strongly encouraged to read <a href="http://www.icu-project.org/userguide/Collate_Intro.html"> the users
 * guide</a> for more information about the collation service before using this class.
 * </p>
 * 
 * <p>
 * Create a RuleBasedCollator from a locale by calling the getInstance(Locale) factory method in the base class
 * Collator. Collator.getInstance(Locale) creates a RuleBasedCollator object based on the collation rules defined by the
 * argument locale. If a customized collation ordering ar attributes is required, use the RuleBasedCollator(String)
 * constructor with the appropriate rules. The customized RuleBasedCollator will base its ordering on UCA, while
 * re-adjusting the attributes and orders of the characters in the specified rule accordingly.
 * </p>
 * 
 * <p>
 * RuleBasedCollator provides correct collation orders for most locales supported in ICU. If specific data for a locale
 * is not available, the orders eventually falls back to the <a href="http://www.unicode.org/unicode/reports/tr10/">UCA
 * collation order </a>.
 * </p>
 * 
 * <p>
 * For information about the collation rule syntax and details about customization, please refer to the <a
 * href="http://www.icu-project.org/userguide/Collate_Customization.html"> Collation customization</a> section of the
 * user's guide.
 * </p>
 * 
 * <p>
 * <strong>Note</strong> that there are some differences between the Collation rule syntax used in Java and ICU4J:
 * 
 * <ul>
 * <li>According to the JDK documentation: <i>
 * <p>
 * Modifier '!' : Turns on Thai/Lao vowel-consonant swapping. If this rule is in force when a Thai vowel of the range
 * &#92;U0E40-&#92;U0E44 precedes a Thai consonant of the range &#92;U0E01-&#92;U0E2E OR a Lao vowel of the range
 * &#92;U0EC0-&#92;U0EC4 precedes a Lao consonant of the range &#92;U0E81-&#92;U0EAE then the vowel is placed after the
 * consonant for collation purposes.
 * </p>
 * <p>
 * If a rule is without the modifier '!', the Thai/Lao vowel-consonant swapping is not turned on.
 * </p>
 * </i>
 * <p>
 * ICU4J's RuleBasedCollator does not support turning off the Thai/Lao vowel-consonant swapping, since the UCA clearly
 * states that it has to be supported to ensure a correct sorting order. If a '!' is encountered, it is ignored.
 * </p>
 * <li>As mentioned in the documentation of the base class Collator, compatibility decomposition mode is not supported.
 * </ul>
 * <p>
 * <strong>Examples</strong>
 * </p>
 * <p>
 * Creating Customized RuleBasedCollators: <blockquote>
 * 
 * <pre>
 * String simple = "&amp; a &lt; b &lt; c &lt; d";
 * RuleBasedCollator simpleCollator = new RuleBasedCollator(simple);
 *
 * String norwegian = "&amp; a , A &lt; b , B &lt; c , C &lt; d , D &lt; e , E "
 *                    + "&lt; f , F &lt; g , G &lt; h , H &lt; i , I &lt; j , "
 *                    + "J &lt; k , K &lt; l , L &lt; m , M &lt; n , N &lt; "
 *                    + "o , O &lt; p , P &lt; q , Q &lt r , R &lt s , S &lt; "
 *                    + "t , T &lt; u , U &lt; v , V &lt; w , W &lt; x , X "
 *                    + "&lt; y , Y &lt; z , Z &lt; &#92;u00E5 = a&#92;u030A "
 *                    + ", &#92;u00C5 = A&#92;u030A ; aa , AA &lt; &#92;u00E6 "
 *                    + ", &#92;u00C6 &lt; &#92;u00F8 , &#92;u00D8";
 * RuleBasedCollator norwegianCollator = new RuleBasedCollator(norwegian);
 * </pre>
 * 
 * </blockquote>
 * 
 * Concatenating rules to combine <code>Collator</code>s: <blockquote>
 * 
 * <pre>
 * // Create an en_US Collator object
 * RuleBasedCollator en_USCollator = (RuleBasedCollator)
 *     Collator.getInstance(new Locale("en", "US", ""));
 * // Create a da_DK Collator object
 * RuleBasedCollator da_DKCollator = (RuleBasedCollator)
 *     Collator.getInstance(new Locale("da", "DK", ""));
 * // Combine the two
 * // First, get the collation rules from en_USCollator
 * String en_USRules = en_USCollator.getRules();
 * // Second, get the collation rules from da_DKCollator
 * String da_DKRules = da_DKCollator.getRules();
 * RuleBasedCollator newCollator =
 *                             new RuleBasedCollator(en_USRules + da_DKRules);
 * // newCollator has the combined rules
 * </pre>
 * 
 * </blockquote>
 * 
 * Making changes to an existing RuleBasedCollator to create a new <code>Collator</code> object, by appending changes to
 * the existing rule: <blockquote>
 * 
 * <pre>
 * // Create a new Collator object with additional rules
 * String addRules = "&amp; C &lt; ch, cH, Ch, CH";
 * RuleBasedCollator myCollator =
 *     new RuleBasedCollator(en_USCollator.getRules() + addRules);
 * // myCollator contains the new rules
  * </pre>
 * 
 * </blockquote>
 * 
 * How to change the order of non-spacing accents: <blockquote>
 * 
 * <pre>
 * // old rule with main accents
 * String oldRules = "= &#92;u0301 ; &#92;u0300 ; &#92;u0302 ; &#92;u0308 "
 *                 + "; &#92;u0327 ; &#92;u0303 ; &#92;u0304 ; &#92;u0305 "
 *                 + "; &#92;u0306 ; &#92;u0307 ; &#92;u0309 ; &#92;u030A "
 *                 + "; &#92;u030B ; &#92;u030C ; &#92;u030D ; &#92;u030E "
 *                 + "; &#92;u030F ; &#92;u0310 ; &#92;u0311 ; &#92;u0312 "
 *                 + "&lt; a , A ; ae, AE ; &#92;u00e6 , &#92;u00c6 "
 *                 + "&lt; b , B &lt; c, C &lt; e, E &amp; C &lt; d , D";
 * // change the order of accent characters
 * String addOn = "&amp; &#92;u0300 ; &#92;u0308 ; &#92;u0302";
 * RuleBasedCollator myCollator = new RuleBasedCollator(oldRules + addOn);
 * </pre>
 * 
 * </blockquote>
 * 
 * Putting in a new primary ordering before the default setting, e.g. sort English characters before or after Japanese
 * characters in the Japanese <code>Collator</code>: <blockquote>
 * 
 * <pre>
 * // get en_US Collator rules
 * RuleBasedCollator en_USCollator
 *                        = (RuleBasedCollator)Collator.getInstance(Locale.US);
 * // add a few Japanese characters to sort before English characters
 * // suppose the last character before the first base letter 'a' in
 * // the English collation rule is &#92;u2212
 * String jaString = "& &#92;u2212 &lt &#92;u3041, &#92;u3042 &lt &#92;u3043, "
 *                   + "&#92;u3044";
 * RuleBasedCollator myJapaneseCollator
 *              = new RuleBasedCollator(en_USCollator.getRules() + jaString);
 * </pre>
 * 
 * </blockquote>
 * </p>
 * <p>
 * This class is not subclassable
 * </p>
 * 
 * @author Syn Wee Quek
 * @stable ICU 2.8
 */
public final class RuleBasedCollator extends Collator {
    // public constructors ---------------------------------------------------

    /**
     * <p>
     * Constructor that takes the argument rules for customization. The collator will be based on UCA, with the
     * attributes and re-ordering of the characters specified in the argument rules.
     * </p>
     * <p>
     * See the user guide's section on <a href="http://www.icu-project.org/userguide/Collate_Customization.html">
     * Collation Customization</a> for details on the rule syntax.
     * </p>
     * 
     * @param rules
     *            the collation rules to build the collation table from.
     * @exception ParseException
     *                and IOException thrown. ParseException thrown when argument rules have an invalid syntax.
     *                IOException thrown when an error occured while reading internal data.
     * @stable ICU 2.8
     */
    public RuleBasedCollator(String rules) throws Exception {
        checkUCA();
        if (rules == null) {
            throw new IllegalArgumentException("Collation rules can not be null");
        }
        init(rules);
    }

    // public methods --------------------------------------------------------

    /**
     * Clones the RuleBasedCollator
     * 
     * @return a new instance of this RuleBasedCollator object
     * @stable ICU 2.8
     */
    public Object clone() throws CloneNotSupportedException {
        RuleBasedCollator result = (RuleBasedCollator) super.clone();
        if (latinOneCEs_ != null) {
            result.m_reallocLatinOneCEs_ = true;
            result.m_ContInfo_ = new ContractionInfo();
        }

        // since all collation data in the RuleBasedCollator do not change
        // we can safely assign the result.fields to this collator
        result.initUtility(false); // let the new clone have their own util
        // iterators
        return result;
    }

    /**
     * Return a CollationElementIterator for the given String.
     * 
     * @see CollationElementIterator
     * @stable ICU 2.8
     */
    public CollationElementIterator getCollationElementIterator(String source) {
        return new CollationElementIterator(source, this);
    }

    /**
     * Return a CollationElementIterator for the given CharacterIterator. The source iterator's integrity will be
     * preserved since a new copy will be created for use.
     * 
     * @see CollationElementIterator
     * @stable ICU 2.8
     */
    public CollationElementIterator getCollationElementIterator(CharacterIterator source) {
        CharacterIterator newsource = (CharacterIterator) source.clone();
        return new CollationElementIterator(newsource, this);
    }

    /**
     * Return a CollationElementIterator for the given UCharacterIterator. The source iterator's integrity will be
     * preserved since a new copy will be created for use.
     * 
     * @see CollationElementIterator
     * @stable ICU 2.8
     */
    public CollationElementIterator getCollationElementIterator(UCharacterIterator source) {
        return new CollationElementIterator(source, this);
    }

    // public setters --------------------------------------------------------

    /**
     * Sets the Hiragana Quaternary mode to be on or off. When the Hiragana Quaternary mode is turned on, the collator
     * positions Hiragana characters before all non-ignorable characters in QUATERNARY strength. This is to produce a
     * correct JIS collation order, distinguishing between Katakana and Hiragana characters.
     * 
     * @param flag
     *            true if Hiragana Quaternary mode is to be on, false otherwise
     * @see #setHiraganaQuaternaryDefault
     * @see #isHiraganaQuaternary
     * @stable ICU 2.8
     */
    public void setHiraganaQuaternary(boolean flag) {
        m_isHiragana4_ = flag;
        updateInternalState();
    }

    /**
     * Sets the Hiragana Quaternary mode to the initial mode set during construction of the RuleBasedCollator. See
     * setHiraganaQuaternary(boolean) for more details.
     * 
     * @see #setHiraganaQuaternary(boolean)
     * @see #isHiraganaQuaternary
     * @stable ICU 2.8
     */
    public void setHiraganaQuaternaryDefault() {
        m_isHiragana4_ = m_defaultIsHiragana4_;
        updateInternalState();
    }

    /**
     * Sets whether uppercase characters sort before lowercase characters or vice versa, in strength TERTIARY. The
     * default mode is false, and so lowercase characters sort before uppercase characters. If true, sort upper case
     * characters first.
     * 
     * @param upperfirst
     *            true to sort uppercase characters before lowercase characters, false to sort lowercase characters
     *            before uppercase characters
     * @see #isLowerCaseFirst
     * @see #isUpperCaseFirst
     * @see #setLowerCaseFirst
     * @see #setCaseFirstDefault
     * @stable ICU 2.8
     */
    public void setUpperCaseFirst(boolean upperfirst) {
        if (upperfirst) {
            if (m_caseFirst_ != AttributeValue.UPPER_FIRST_) {
                latinOneRegenTable_ = true;
            }
            m_caseFirst_ = AttributeValue.UPPER_FIRST_;
        } else {
            if (m_caseFirst_ != AttributeValue.OFF_) {
                latinOneRegenTable_ = true;
            }
            m_caseFirst_ = AttributeValue.OFF_;
        }
        updateInternalState();
    }

    /**
     * Sets the orders of lower cased characters to sort before upper cased characters, in strength TERTIARY. The
     * default mode is false. If true is set, the RuleBasedCollator will sort lower cased characters before the upper
     * cased ones. Otherwise, if false is set, the RuleBasedCollator will ignore case preferences.
     * 
     * @param lowerfirst
     *            true for sorting lower cased characters before upper cased characters, false to ignore case
     *            preferences.
     * @see #isLowerCaseFirst
     * @see #isUpperCaseFirst
     * @see #setUpperCaseFirst
     * @see #setCaseFirstDefault
     * @stable ICU 2.8
     */
    public void setLowerCaseFirst(boolean lowerfirst) {
        if (lowerfirst) {
            if (m_caseFirst_ != AttributeValue.LOWER_FIRST_) {
                latinOneRegenTable_ = true;
            }
            m_caseFirst_ = AttributeValue.LOWER_FIRST_;
        } else {
            if (m_caseFirst_ != AttributeValue.OFF_) {
                latinOneRegenTable_ = true;
            }
            m_caseFirst_ = AttributeValue.OFF_;
        }
        updateInternalState();
    }

    /**
     * Sets the case first mode to the initial mode set during construction of the RuleBasedCollator. See
     * setUpperCaseFirst(boolean) and setLowerCaseFirst(boolean) for more details.
     * 
     * @see #isLowerCaseFirst
     * @see #isUpperCaseFirst
     * @see #setLowerCaseFirst(boolean)
     * @see #setUpperCaseFirst(boolean)
     * @stable ICU 2.8
     */
    public final void setCaseFirstDefault() {
        if (m_caseFirst_ != m_defaultCaseFirst_) {
            latinOneRegenTable_ = true;
        }
        m_caseFirst_ = m_defaultCaseFirst_;
        updateInternalState();
    }

    /**
     * Sets the alternate handling mode to the initial mode set during construction of the RuleBasedCollator. See
     * setAlternateHandling(boolean) for more details.
     * 
     * @see #setAlternateHandlingShifted(boolean)
     * @see #isAlternateHandlingShifted()
     * @stable ICU 2.8
     */
    public void setAlternateHandlingDefault() {
        m_isAlternateHandlingShifted_ = m_defaultIsAlternateHandlingShifted_;
        updateInternalState();
    }

    /**
     * Sets the case level mode to the initial mode set during construction of the RuleBasedCollator. See
     * setCaseLevel(boolean) for more details.
     * 
     * @see #setCaseLevel(boolean)
     * @see #isCaseLevel
     * @stable ICU 2.8
     */
    public void setCaseLevelDefault() {
        m_isCaseLevel_ = m_defaultIsCaseLevel_;
        updateInternalState();
    }

    /**
     * Sets the decomposition mode to the initial mode set during construction of the RuleBasedCollator. See
     * setDecomposition(int) for more details.
     * 
     * @see #getDecomposition
     * @see #setDecomposition(int)
     * @stable ICU 2.8
     */
    public void setDecompositionDefault() {
        setDecomposition(m_defaultDecomposition_);
        updateInternalState();
    }

    /**
     * Sets the French collation mode to the initial mode set during construction of the RuleBasedCollator. See
     * setFrenchCollation(boolean) for more details.
     * 
     * @see #isFrenchCollation
     * @see #setFrenchCollation(boolean)
     * @stable ICU 2.8
     */
    public void setFrenchCollationDefault() {
        if (m_isFrenchCollation_ != m_defaultIsFrenchCollation_) {
            latinOneRegenTable_ = true;
        }
        m_isFrenchCollation_ = m_defaultIsFrenchCollation_;
        updateInternalState();
    }

    /**
     * Sets the collation strength to the initial mode set during the construction of the RuleBasedCollator. See
     * setStrength(int) for more details.
     * 
     * @see #setStrength(int)
     * @see #getStrength
     * @stable ICU 2.8
     */
    public void setStrengthDefault() {
        setStrength(m_defaultStrength_);
        updateInternalState();
    }

    /**
     * Method to set numeric collation to its default value. When numeric collation is turned on, this Collator
     * generates a collation key for the numeric value of substrings of digits. This is a way to get '100' to sort AFTER
     * '2'
     * 
     * @see #getNumericCollation
     * @see #setNumericCollation
     * @stable ICU 2.8
     */
    public void setNumericCollationDefault() {
        setNumericCollation(m_defaultIsNumericCollation_);
        updateInternalState();
    }

    /**
     * Sets the mode for the direction of SECONDARY weights to be used in French collation. The default value is false,
     * which treats SECONDARY weights in the order they appear. If set to true, the SECONDARY weights will be sorted
     * backwards. See the section on <a href="http://www.icu-project.org/userguide/Collate_ServiceArchitecture.html">
     * French collation</a> for more information.
     * 
     * @param flag
     *            true to set the French collation on, false to set it off
     * @stable ICU 2.8
     * @see #isFrenchCollation
     * @see #setFrenchCollationDefault
     */
    public void setFrenchCollation(boolean flag) {
        if (m_isFrenchCollation_ != flag) {
            latinOneRegenTable_ = true;
        }
        m_isFrenchCollation_ = flag;
        updateInternalState();
    }

    /**
     * Sets the alternate handling for QUATERNARY strength to be either shifted or non-ignorable. See the UCA definition
     * on <a href="http://www.unicode.org/unicode/reports/tr10/#Variable_Weighting"> Alternate Weighting</a>. This
     * attribute will only be effective when QUATERNARY strength is set. The default value for this mode is false,
     * corresponding to the NON_IGNORABLE mode in UCA. In the NON-IGNORABLE mode, the RuleBasedCollator will treats all
     * the codepoints with non-ignorable primary weights in the same way. If the mode is set to true, the behaviour
     * corresponds to SHIFTED defined in UCA, this causes codepoints with PRIMARY orders that are equal or below the
     * variable top value to be ignored in PRIMARY order and moved to the QUATERNARY order.
     * 
     * @param shifted
     *            true if SHIFTED behaviour for alternate handling is desired, false for the NON_IGNORABLE behaviour.
     * @see #isAlternateHandlingShifted
     * @see #setAlternateHandlingDefault
     * @stable ICU 2.8
     */
    public void setAlternateHandlingShifted(boolean shifted) {
        m_isAlternateHandlingShifted_ = shifted;
        updateInternalState();
    }

    /**
     * <p>
     * When case level is set to true, an additional weight is formed between the SECONDARY and TERTIARY weight, known
     * as the case level. The case level is used to distinguish large and small Japanese Kana characters. Case level
     * could also be used in other situations. For example to distinguish certain Pinyin characters. The default value
     * is false, which means the case level is not generated. The contents of the case level are affected by the case
     * first mode. A simple way to ignore accent differences in a string is to set the strength to PRIMARY and enable
     * case level.
     * </p>
     * <p>
     * See the section on <a href="http://www.icu-project.org/userguide/Collate_ServiceArchitecture.html"> case
     * level</a> for more information.
     * </p>
     * 
     * @param flag
     *            true if case level sorting is required, false otherwise
     * @stable ICU 2.8
     * @see #setCaseLevelDefault
     * @see #isCaseLevel
     */
    public void setCaseLevel(boolean flag) {
        m_isCaseLevel_ = flag;
        updateInternalState();
    }

    /**
     * <p>
     * Sets this Collator's strength property. The strength property determines the minimum level of difference
     * considered significant during comparison.
     * </p>
     * <p>
     * See the Collator class description for an example of use.
     * </p>
     * 
     * @param newStrength
     *            the new strength value.
     * @see #getStrength
     * @see #setStrengthDefault
     * @see #PRIMARY
     * @see #SECONDARY
     * @see #TERTIARY
     * @see #QUATERNARY
     * @see #IDENTICAL
     * @exception IllegalArgumentException
     *                If the new strength value is not one of PRIMARY, SECONDARY, TERTIARY, QUATERNARY or IDENTICAL.
     * @stable ICU 2.8
     */
    public void setStrength(int newStrength) {
        super.setStrength(newStrength);
        updateInternalState();
    }

    /**
     * <p>
     * Variable top is a two byte primary value which causes all the codepoints with primary values that are less or
     * equal than the variable top to be shifted when alternate handling is set to SHIFTED.
     * </p>
     * <p>
     * Sets the variable top to a collation element value of a string supplied.
     * </p>
     * 
     * @param varTop
     *            one or more (if contraction) characters to which the variable top should be set
     * @return a int value containing the value of the variable top in upper 16 bits. Lower 16 bits are undefined.
     * @exception IllegalArgumentException
     *                is thrown if varTop argument is not a valid variable top element. A variable top element is
     *                invalid when
     *                <ul>
     *                <li>it is a contraction that does not exist in the Collation order
     *                <li>when the PRIMARY strength collation element for the variable top has more than two bytes
     *                <li>when the varTop argument is null or zero in length.
     *                </ul>
     * @see #getVariableTop
     * @see RuleBasedCollator#setAlternateHandlingShifted
     * @stable ICU 2.6
     */
    public int setVariableTop(String varTop) {
        if (varTop == null || varTop.length() == 0) {
            throw new IllegalArgumentException("Variable top argument string can not be null or zero in length.");
        }
        if (m_srcUtilIter_ == null) {
            initUtility(true);
        }

        m_srcUtilColEIter_.setText(varTop);
        int ce = m_srcUtilColEIter_.next();

        // here we check if we have consumed all characters
        // you can put in either one character or a contraction
        // you shouldn't put more...
        if (m_srcUtilColEIter_.getOffset() != varTop.length() || ce == CollationElementIterator.NULLORDER) {
            throw new IllegalArgumentException("Variable top argument string is a contraction that does not exist "
                    + "in the Collation order");
        }

        int nextCE = m_srcUtilColEIter_.next();

        if ((nextCE != CollationElementIterator.NULLORDER)
                && (!isContinuation(nextCE) || (nextCE & CE_PRIMARY_MASK_) != 0)) {
            throw new IllegalArgumentException("Variable top argument string can only have a single collation "
                    + "element that has less than or equal to two PRIMARY strength " + "bytes");
        }

        m_variableTopValue_ = (ce & CE_PRIMARY_MASK_) >> 16;

        return ce & CE_PRIMARY_MASK_;
    }

    /**
     * Sets the variable top to a collation element value supplied. Variable top is set to the upper 16 bits. Lower 16
     * bits are ignored.
     * 
     * @param varTop
     *            Collation element value, as returned by setVariableTop or getVariableTop
     * @see #getVariableTop
     * @see #setVariableTop(String)
     * @stable ICU 2.6
     */
    public void setVariableTop(int varTop) {
        m_variableTopValue_ = (varTop & CE_PRIMARY_MASK_) >> 16;
    }

    /**
     * When numeric collation is turned on, this Collator generates a collation key for the numeric value of substrings
     * of digits. This is a way to get '100' to sort AFTER '2'
     * 
     * @param flag
     *            true to turn numeric collation on and false to turn it off
     * @see #getNumericCollation
     * @see #setNumericCollationDefault
     * @stable ICU 2.8
     */
    public void setNumericCollation(boolean flag) {
        // sort substrings of digits as numbers
        m_isNumericCollation_ = flag;
        updateInternalState();
    }

    /** 
     * Set the reordering codes for this collator.
     * The reordering codes are a combination of UScript and ReorderingCodes. These
     * allow the order of these groups to be changed as a group.  
     * @param order the reordering codes to apply to this collator, if null then clears the reordering
     * @see #getReorderCodes
     * @internal
     * @deprecated This API is ICU internal only.
     */ 
    public void setReorderCodes(int... order) {
        if (order != null && order.length > 0) {
            m_reorderCodes_ = order.clone();
        } else {
            m_reorderCodes_ = null;
        }
        buildPermutationTable();
    }

    // public getters --------------------------------------------------------

    /**
     * Gets the collation rules for this RuleBasedCollator. Equivalent to String getRules(RuleOption.FULL_RULES).
     * 
     * @return returns the collation rules
     * @see #getRules(boolean)
     * @stable ICU 2.8
     */
    public String getRules() {
        return m_rules_;
    }

    /**
     * Returns current rules. The argument defines whether full rules (UCA + tailored) rules are returned or just the
     * tailoring.
     * 
     * @param fullrules
     *            true if the rules that defines the full set of collation order is required, otherwise false for
     *            returning only the tailored rules
     * @return the current rules that defines this Collator.
     * @see #getRules()
     * @stable ICU 2.6
     */
    public String getRules(boolean fullrules) {
        if (!fullrules) {
            return m_rules_;
        }
        // take the UCA rules and append real rules at the end
        return UCA_.m_rules_.concat(m_rules_);
    }

    /**
     * Get an UnicodeSet that contains all the characters and sequences tailored in this collator.
     * 
     * @return a pointer to a UnicodeSet object containing all the code points and sequences that may sort differently
     *         than in the UCA.
     * @stable ICU 2.4
     */
    public UnicodeSet getTailoredSet() {
        try {
            CollationRuleParser src = new CollationRuleParser(getRules());
            return src.getTailoredSet();
        } catch (Exception e) {
            throw new IllegalStateException("A tailoring rule should not " + "have errors. Something is quite wrong!");
        }
    }

    private class contContext {
        RuleBasedCollator coll;
        UnicodeSet contractions;
        UnicodeSet expansions;
        UnicodeSet removedContractions;
        boolean addPrefixes;

        contContext(RuleBasedCollator coll, UnicodeSet contractions, UnicodeSet expansions,
                UnicodeSet removedContractions, boolean addPrefixes) {
            this.coll = coll;
            this.contractions = contractions;
            this.expansions = expansions;
            this.removedContractions = removedContractions;
            this.addPrefixes = addPrefixes;
        }
    }

    private void addSpecial(contContext c, StringBuilder buffer, int CE) {
        StringBuilder b = new StringBuilder();
        int offset = (CE & 0xFFFFFF) - c.coll.m_contractionOffset_;
        int newCE = c.coll.m_contractionCE_[offset];
        // we might have a contraction that ends from previous level
        if (newCE != CollationElementIterator.CE_NOT_FOUND_) {
            if (isSpecial(CE) && getTag(CE) == CollationElementIterator.CE_CONTRACTION_TAG_ && isSpecial(newCE)
                    && getTag(newCE) == CollationElementIterator.CE_SPEC_PROC_TAG_ && c.addPrefixes) {
                addSpecial(c, buffer, newCE);
            }
            if (buffer.length() > 1) {
                if (c.contractions != null) {
                    c.contractions.add(buffer.toString());
                }
                if (c.expansions != null && isSpecial(CE) && getTag(CE) == CollationElementIterator.CE_EXPANSION_TAG_) {
                    c.expansions.add(buffer.toString());
                }
            }
        }

        offset++;
        // check whether we're doing contraction or prefix
        if (getTag(CE) == CollationElementIterator.CE_SPEC_PROC_TAG_ && c.addPrefixes) {
            while (c.coll.m_contractionIndex_[offset] != 0xFFFF) {
                b.delete(0, b.length());
                b.append(buffer);
                newCE = c.coll.m_contractionCE_[offset];
                b.insert(0, c.coll.m_contractionIndex_[offset]);
                if (isSpecial(newCE)
                        && (getTag(newCE) == CollationElementIterator.CE_CONTRACTION_TAG_ || getTag(newCE) == CollationElementIterator.CE_SPEC_PROC_TAG_)) {
                    addSpecial(c, b, newCE);
                } else {
                    if (c.contractions != null) {
                        c.contractions.add(b.toString());
                    }
                    if (c.expansions != null && isSpecial(newCE)
                            && getTag(newCE) == CollationElementIterator.CE_EXPANSION_TAG_) {
                        c.expansions.add(b.toString());
                    }
                }
                offset++;
            }
        } else if (getTag(CE) == CollationElementIterator.CE_CONTRACTION_TAG_) {
            while (c.coll.m_contractionIndex_[offset] != 0xFFFF) {
                b.delete(0, b.length());
                b.append(buffer);
                newCE = c.coll.m_contractionCE_[offset];
                b.append(c.coll.m_contractionIndex_[offset]);
                if (isSpecial(newCE)
                        && (getTag(newCE) == CollationElementIterator.CE_CONTRACTION_TAG_ || getTag(newCE) == CollationElementIterator.CE_SPEC_PROC_TAG_)) {
                    addSpecial(c, b, newCE);
                } else {
                    if (c.contractions != null) {
                        c.contractions.add(b.toString());
                    }
                    if (c.expansions != null && isSpecial(newCE)
                            && getTag(newCE) == CollationElementIterator.CE_EXPANSION_TAG_) {
                        c.expansions.add(b.toString());
                    }
                }
                offset++;
            }
        }
    }

    private void processSpecials(contContext c) {
        int internalBufferSize = 512;
        TrieIterator trieiterator = new TrieIterator(c.coll.m_trie_);
        RangeValueIterator.Element element = new RangeValueIterator.Element();
        while (trieiterator.next(element)) {
            int start = element.start;
            int limit = element.limit;
            int CE = element.value;
            StringBuilder contraction = new StringBuilder(internalBufferSize);

            if (isSpecial(CE)) {
                if (((getTag(CE) == CollationElementIterator.CE_SPEC_PROC_TAG_ && c.addPrefixes) || getTag(CE) == CollationElementIterator.CE_CONTRACTION_TAG_)) {
                    while (start < limit) {
                        // if there are suppressed contractions, we don't
                        // want to add them.
                        if (c.removedContractions != null && c.removedContractions.contains(start)) {
                            start++;
                            continue;
                        }
                        // we start our contraction from middle, since we don't know if it
                        // will grow toward right or left
                        contraction.append((char) start);
                        addSpecial(c, contraction, CE);
                        start++;
                    }
                } else if (c.expansions != null && getTag(CE) == CollationElementIterator.CE_EXPANSION_TAG_) {
                    while (start < limit) {
                        c.expansions.add(start++);
                    }
                }
            }
        }
    }

    /**
     * Gets unicode sets containing contractions and/or expansions of a collator
     * 
     * @param contractions
     *            if not null, set to contain contractions
     * @param expansions
     *            if not null, set to contain expansions
     * @param addPrefixes
     *            add the prefix contextual elements to contractions
     * @throws Exception
     *             Throws an exception if any errors occurs.
     * @stable ICU 3.4
     */
    public void getContractionsAndExpansions(UnicodeSet contractions, UnicodeSet expansions, boolean addPrefixes)
    throws Exception {
        if (contractions != null) {
            contractions.clear();
        }
        if (expansions != null) {
            expansions.clear();
        }
        String rules = getRules();
        try {
            CollationRuleParser src = new CollationRuleParser(rules);
            contContext c = new contContext(RuleBasedCollator.UCA_, contractions, expansions, src.m_removeSet_,
                    addPrefixes);

            // Add the UCA contractions
            processSpecials(c);
            // This is collator specific. Add contractions from a collator
            c.coll = this;
            c.removedContractions = null;
            processSpecials(c);
        } catch (Exception e) {
            throw e;
        }
    }

    /**
     * <p>
     * Get a Collation key for the argument String source from this RuleBasedCollator.
     * </p>
     * <p>
     * General recommendation: <br>
     * If comparison are to be done to the same String multiple times, it would be more efficient to generate
     * CollationKeys for the Strings and use CollationKey.compareTo(CollationKey) for the comparisons. If the each
     * Strings are compared to only once, using the method RuleBasedCollator.compare(String, String) will have a better
     * performance.
     * </p>
     * <p>
     * See the class documentation for an explanation about CollationKeys.
     * </p>
     * 
     * @param source
     *            the text String to be transformed into a collation key.
     * @return the CollationKey for the given String based on this RuleBasedCollator's collation rules. If the source
     *         String is null, a null CollationKey is returned.
     * @see CollationKey
     * @see #compare(String, String)
     * @see #getRawCollationKey
     * @stable ICU 2.8
     */
    public CollationKey getCollationKey(String source) {
        if (source == null) {
            return null;
        }
        m_utilRawCollationKey_ = getRawCollationKey(source, m_utilRawCollationKey_);
        return new CollationKey(source, m_utilRawCollationKey_);
    }

    /**
     * Gets the simpler form of a CollationKey for the String source following the rules of this Collator and stores the
     * result into the user provided argument key. If key has a internal byte array of length that's too small for the
     * result, the internal byte array will be grown to the exact required size.
     * 
     * @param source
     *            the text String to be transformed into a RawCollationKey
     * @param key
     *            output RawCollationKey to store results
     * @return If key is null, a new instance of RawCollationKey will be created and returned, otherwise the user
     *         provided key will be returned.
     * @see #getCollationKey
     * @see #compare(String, String)
     * @see RawCollationKey
     * @stable ICU 2.8
     */
    public RawCollationKey getRawCollationKey(String source, RawCollationKey key) {
        if (source == null) {
            return null;
        }
        int strength = getStrength();
        m_utilCompare0_ = m_isCaseLevel_;
        // m_utilCompare1_ = true;
        m_utilCompare2_ = strength >= SECONDARY;
        m_utilCompare3_ = strength >= TERTIARY;
        m_utilCompare4_ = strength >= QUATERNARY;
        m_utilCompare5_ = strength == IDENTICAL;

        m_utilBytesCount0_ = 0;
        m_utilBytesCount1_ = 0;
        m_utilBytesCount2_ = 0;
        m_utilBytesCount3_ = 0;
        m_utilBytesCount4_ = 0;
        // m_utilBytesCount5_ = 0;
        // m_utilCount0_ = 0;
        // m_utilCount1_ = 0;
        m_utilCount2_ = 0;
        m_utilCount3_ = 0;
        m_utilCount4_ = 0;
        // m_utilCount5_ = 0;
        boolean doFrench = m_isFrenchCollation_ && m_utilCompare2_;
        // TODO: UCOL_COMMON_BOT4 should be a function of qShifted.
        // If we have no qShifted, we don't need to set UCOL_COMMON_BOT4 so
        // high.
        int commonBottom4 = ((m_variableTopValue_ >>> 8) + 1) & LAST_BYTE_MASK_;
        byte hiragana4 = 0;
        if (m_isHiragana4_ && m_utilCompare4_) {
            // allocate one more space for hiragana, value for hiragana
            hiragana4 = (byte) commonBottom4;
            commonBottom4++;
        }

        int bottomCount4 = 0xFF - commonBottom4;
        // If we need to normalize, we'll do it all at once at the beginning!
        if (m_utilCompare5_ && Normalizer.quickCheck(source, Normalizer.NFD, 0) != Normalizer.YES) {
            // if it is identical strength, we have to normalize the string to
            // NFD so that it will be appended correctly to the end of the sort
            // key
            source = Normalizer.decompose(source, false);
        } else if (getDecomposition() != NO_DECOMPOSITION
                && Normalizer.quickCheck(source, Normalizer.FCD, 0) != Normalizer.YES) {
            // for the rest of the strength, if decomposition is on, FCD is
            // enough for us to work on.
            source = Normalizer.normalize(source, Normalizer.FCD);
        }
        getSortKeyBytes(source, doFrench, hiragana4, commonBottom4, bottomCount4);
        if (key == null) {
            key = new RawCollationKey();
        }
        getSortKey(source, doFrench, commonBottom4, bottomCount4, key);
        return key;
    }

    /**
     * Return true if an uppercase character is sorted before the corresponding lowercase character. See
     * setCaseFirst(boolean) for details.
     * 
     * @see #setUpperCaseFirst
     * @see #setLowerCaseFirst
     * @see #isLowerCaseFirst
     * @see #setCaseFirstDefault
     * @return true if upper cased characters are sorted before lower cased characters, false otherwise
     * @stable ICU 2.8
     */
    public boolean isUpperCaseFirst() {
        return (m_caseFirst_ == AttributeValue.UPPER_FIRST_);
    }

    /**
     * Return true if a lowercase character is sorted before the corresponding uppercase character. See
     * setCaseFirst(boolean) for details.
     * 
     * @see #setUpperCaseFirst
     * @see #setLowerCaseFirst
     * @see #isUpperCaseFirst
     * @see #setCaseFirstDefault
     * @return true lower cased characters are sorted before upper cased characters, false otherwise
     * @stable ICU 2.8
     */
    public boolean isLowerCaseFirst() {
        return (m_caseFirst_ == AttributeValue.LOWER_FIRST_);
    }

    /**
     * Checks if the alternate handling behaviour is the UCA defined SHIFTED or NON_IGNORABLE. If return value is true,
     * then the alternate handling attribute for the Collator is SHIFTED. Otherwise if return value is false, then the
     * alternate handling attribute for the Collator is NON_IGNORABLE See setAlternateHandlingShifted(boolean) for more
     * details.
     * 
     * @return true or false
     * @see #setAlternateHandlingShifted(boolean)
     * @see #setAlternateHandlingDefault
     * @stable ICU 2.8
     */
    public boolean isAlternateHandlingShifted() {
        return m_isAlternateHandlingShifted_;
    }

    /**
     * Checks if case level is set to true. See setCaseLevel(boolean) for details.
     * 
     * @return the case level mode
     * @see #setCaseLevelDefault
     * @see #isCaseLevel
     * @see #setCaseLevel(boolean)
     * @stable ICU 2.8
     */
    public boolean isCaseLevel() {
        return m_isCaseLevel_;
    }

    /**
     * Checks if French Collation is set to true. See setFrenchCollation(boolean) for details.
     * 
     * @return true if French Collation is set to true, false otherwise
     * @see #setFrenchCollation(boolean)
     * @see #setFrenchCollationDefault
     * @stable ICU 2.8
     */
    public boolean isFrenchCollation() {
        return m_isFrenchCollation_;
    }

    /**
     * Checks if the Hiragana Quaternary mode is set on. See setHiraganaQuaternary(boolean) for more details.
     * 
     * @return flag true if Hiragana Quaternary mode is on, false otherwise
     * @see #setHiraganaQuaternaryDefault
     * @see #setHiraganaQuaternary(boolean)
     * @stable ICU 2.8
     */
    public boolean isHiraganaQuaternary() {
        return m_isHiragana4_;
    }

    /**
     * Gets the variable top value of a Collator. Lower 16 bits are undefined and should be ignored.
     * 
     * @return the variable top value of a Collator.
     * @see #setVariableTop
     * @stable ICU 2.6
     */
    public int getVariableTop() {
        return m_variableTopValue_ << 16;
    }

    /**
     * Method to retrieve the numeric collation value. When numeric collation is turned on, this Collator generates a
     * collation key for the numeric value of substrings of digits. This is a way to get '100' to sort AFTER '2'
     * 
     * @see #setNumericCollation
     * @see #setNumericCollationDefault
     * @return true if numeric collation is turned on, false otherwise
     * @stable ICU 2.8
     */
    public boolean getNumericCollation() {
        return m_isNumericCollation_;
    }

    /**  
     * Retrieve the reordering codes for this collator.
     * These reordering codes are a combination of UScript and ReorderCodes.
     * @see #setReorderCodes
     * @return the reordering codes for this collator if they have been set, null otherwise. 
     * @internal
     * @deprecated This API is ICU internal only.
     */ 
    public int[] getReorderCodes() {
        if (m_reorderCodes_ != null) {
            return m_reorderCodes_.clone();
        } else {
            return null;
        }
    }

    /**
     * Retrieve the reorder codes that are grouped with the given reorder code. Some reorder codes will
     * be grouped and must reorder together.
     * 
     * @see #setReorderCodes
     * @see #getReorderCodes
     * @param reorderCode code for which equivalents to be retrieved
     * @return the set of all reorder codes in the same group as the given reorder code.
     * @internal
     * @deprecated This API is ICU internal only.
     */
    public static int[] getReorderingCodesGroup(int reorderCode) {
        Set<Integer> equivalentCodesSet = new HashSet<Integer>();
        int[] leadBytes = RuleBasedCollator.LEADBYTE_CONSTANTS_.getLeadBytesForReorderCode(reorderCode);
        for (int leadByte : leadBytes) {
            int[] codes = RuleBasedCollator.LEADBYTE_CONSTANTS_.getReorderCodesForLeadByte(leadByte);
            for (int code : codes) {
                equivalentCodesSet.add(code);
            }
        }
        int[] equivalentCodes = new int[equivalentCodesSet.size()];
        int i = 0;
        for (int code : equivalentCodesSet) {
            equivalentCodes[i++] = code;
        }
        return equivalentCodes;
    }

    // public other methods -------------------------------------------------

    /**
     * Compares the equality of two RuleBasedCollator objects. RuleBasedCollator objects are equal if they have the same
     * collation rules and the same attributes.
     * 
     * @param obj
     *            the RuleBasedCollator to be compared to.
     * @return true if this RuleBasedCollator has exactly the same collation behaviour as obj, false otherwise.
     * @stable ICU 2.8
     */
    public boolean equals(Object obj) {
        if (obj == null) {
            return false; // super does class check
        }
        if (this == obj) {
            return true;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        RuleBasedCollator other = (RuleBasedCollator) obj;
        // all other non-transient information is also contained in rules.
        if (getStrength() != other.getStrength() || getDecomposition() != other.getDecomposition()
                || other.m_caseFirst_ != m_caseFirst_ || other.m_caseSwitch_ != m_caseSwitch_
                || other.m_isAlternateHandlingShifted_ != m_isAlternateHandlingShifted_
                || other.m_isCaseLevel_ != m_isCaseLevel_ || other.m_isFrenchCollation_ != m_isFrenchCollation_
                || other.m_isHiragana4_ != m_isHiragana4_) {
            return false;
        }
        if (m_reorderCodes_ != null ^ other.m_reorderCodes_ != null) {
            return false;
        }
        if (m_reorderCodes_ != null) {
            if (m_reorderCodes_.length != other.m_reorderCodes_.length) {
                return false;
            }
            for (int i = 0; i < m_reorderCodes_.length; i++) {
                if (m_reorderCodes_[i] != other.m_reorderCodes_[i]) {
                    return false;
                }
            }
        }
        boolean rules = m_rules_ == other.m_rules_;
        if (!rules && (m_rules_ != null && other.m_rules_ != null)) {
            rules = m_rules_.equals(other.m_rules_);
        }
        if (!rules || !ICUDebug.enabled("collation")) {
            return rules;
        }
        if (m_addition3_ != other.m_addition3_ || m_bottom3_ != other.m_bottom3_
                || m_bottomCount3_ != other.m_bottomCount3_ || m_common3_ != other.m_common3_
                || m_isSimple3_ != other.m_isSimple3_ || m_mask3_ != other.m_mask3_
                || m_minContractionEnd_ != other.m_minContractionEnd_ || m_minUnsafe_ != other.m_minUnsafe_
                || m_top3_ != other.m_top3_ || m_topCount3_ != other.m_topCount3_
                || !Arrays.equals(m_unsafe_, other.m_unsafe_)) {
            return false;
        }
        if (!m_trie_.equals(other.m_trie_)) {
            // we should use the trie iterator here, but then this part is
            // only used in the test.
            for (int i = UCharacter.MAX_VALUE; i >= UCharacter.MIN_VALUE; i--) {
                int v = m_trie_.getCodePointValue(i);
                int otherv = other.m_trie_.getCodePointValue(i);
                if (v != otherv) {
                    int mask = v & (CE_TAG_MASK_ | CE_SPECIAL_FLAG_);
                    if (mask == (otherv & 0xff000000)) {
                        v &= 0xffffff;
                        otherv &= 0xffffff;
                        if (mask == 0xf1000000) {
                            v -= (m_expansionOffset_ << 4);
                            otherv -= (other.m_expansionOffset_ << 4);
                        } else if (mask == 0xf2000000) {
                            v -= m_contractionOffset_;
                            otherv -= other.m_contractionOffset_;
                        }
                        if (v == otherv) {
                            continue;
                        }
                    }
                    return false;
                }
            }
        }
        if (!Arrays.equals(m_contractionCE_, other.m_contractionCE_)
                || !Arrays.equals(m_contractionEnd_, other.m_contractionEnd_)
                || !Arrays.equals(m_contractionIndex_, other.m_contractionIndex_)
                || !Arrays.equals(m_expansion_, other.m_expansion_)
                || !Arrays.equals(m_expansionEndCE_, other.m_expansionEndCE_)) {
            return false;
        }
        // not comparing paddings
        for (int i = 0; i < m_expansionEndCE_.length; i++) {
            if (m_expansionEndCEMaxSize_[i] != other.m_expansionEndCEMaxSize_[i]) {
                return false;
            }
        }
        return true;
    }

    /**
     * Generates a unique hash code for this RuleBasedCollator.
     * 
     * @return the unique hash code for this Collator
     * @stable ICU 2.8
     */
    public int hashCode() {
        String rules = getRules();
        if (rules == null) {
            rules = "";
        }
        return rules.hashCode();
    }

    /**
     * Compares the source text String to the target text String according to the collation rules, strength and
     * decomposition mode for this RuleBasedCollator. 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. </p>
     * <p>
     * General recommendation: <br>
     * If comparison are to be done to the same String multiple times, it would be more efficient to generate
     * CollationKeys for the Strings and use CollationKey.compareTo(CollationKey) for the comparisons. If speed
     * performance is critical and object instantiation is to be reduced, further optimization may be achieved by
     * generating a simpler key of the form RawCollationKey and reusing this RawCollationKey object with the method
     * RuleBasedCollator.getRawCollationKey. Internal byte representation can be directly accessed via RawCollationKey
     * and stored for future use. Like CollationKey, RawCollationKey provides a method RawCollationKey.compareTo for key
     * comparisons. If the each Strings are compared to only once, using the method RuleBasedCollator.compare(String,
     * String) will have a better performance.
     * </p>
     * 
     * @param source
     *            the source text String.
     * @param target
     *            the target text 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
     * @stable ICU 2.8
     */
    public int compare(String source, String target) {
        if (source == target) {
            return 0;
        }

        // Find the length of any leading portion that is equal
        int offset = getFirstUnmatchedOffset(source, target);
        // return compareRegular(source, target, offset);
        if (latinOneUse_) {
            if ((offset < source.length() && source.charAt(offset) > ENDOFLATINONERANGE_)
                    || (offset < target.length() && target.charAt(offset) > ENDOFLATINONERANGE_)) {
                // source or target start with non-latin-1
                return compareRegular(source, target, offset);
            } else {
                return compareUseLatin1(source, target, offset);
            }
        } else {
            return compareRegular(source, target, offset);
        }
    }

    // package private inner interfaces --------------------------------------

    /**
     * Attribute values to be used when setting the Collator options
     */
    static interface AttributeValue {
        /**
         * Indicates that the default attribute value will be used. See individual attribute for details on its default
         * value.
         */
        static final int DEFAULT_ = -1;
        /**
         * Primary collation strength
         */
        static final int PRIMARY_ = Collator.PRIMARY;
        /**
         * Secondary collation strength
         */
        static final int SECONDARY_ = Collator.SECONDARY;
        /**
         * Tertiary collation strength
         */
        static final int TERTIARY_ = Collator.TERTIARY;
        /**
         * Default collation strength
         */
        static final int DEFAULT_STRENGTH_ = Collator.TERTIARY;
        /**
         * Internal use for strength checks in Collation elements
         */
        static final int CE_STRENGTH_LIMIT_ = Collator.TERTIARY + 1;
        /**
         * Quaternary collation strength
         */
        static final int QUATERNARY_ = 3;
        /**
         * Identical collation strength
         */
        static final int IDENTICAL_ = Collator.IDENTICAL;
        /**
         * Internal use for strength checks
         */
        static final int STRENGTH_LIMIT_ = Collator.IDENTICAL + 1;
        /**
         * Turn the feature off - works for FRENCH_COLLATION, CASE_LEVEL, HIRAGANA_QUATERNARY_MODE and
         * DECOMPOSITION_MODE
         */
        static final int OFF_ = 16;
        /**
         * Turn the feature on - works for FRENCH_COLLATION, CASE_LEVEL, HIRAGANA_QUATERNARY_MODE and DECOMPOSITION_MODE
         */
        static final int ON_ = 17;
        /**
         * Valid for ALTERNATE_HANDLING. Alternate handling will be shifted
         */
        static final int SHIFTED_ = 20;
        /**
         * Valid for ALTERNATE_HANDLING. Alternate handling will be non ignorable
         */
        static final int NON_IGNORABLE_ = 21;
        /**
         * Valid for CASE_FIRST - lower case sorts before upper case
         */
        static final int LOWER_FIRST_ = 24;
        /**
         * Upper case sorts before lower case
         */
        static final int UPPER_FIRST_ = 25;
        /**
         * Number of attribute values
         */
        static final int LIMIT_ = 29;
    }

    /**
     * Attributes that collation service understands. All the attributes can take DEFAULT value, as well as the values
     * specific to each one.
     */
    static interface Attribute {
        /**
         * Attribute for direction of secondary weights - used in French. Acceptable values are ON, which results in
         * secondary weights being considered backwards and OFF which treats secondary weights in the order they appear.
         */
        static final int FRENCH_COLLATION_ = 0;
        /**
         * Attribute for handling variable elements. Acceptable values are NON_IGNORABLE (default) which treats all the
         * codepoints with non-ignorable primary weights in the same way, and SHIFTED which causes codepoints with
         * primary weights that are equal or below the variable top value to be ignored on primary level and moved to
         * the quaternary level.
         */
        static final int ALTERNATE_HANDLING_ = 1;
        /**
         * Controls the ordering of upper and lower case letters. Acceptable values are OFF (default), which orders
         * upper and lower case letters in accordance to their tertiary weights, UPPER_FIRST which forces upper case
         * letters to sort before lower case letters, and LOWER_FIRST which does the opposite.
         */
        static final int CASE_FIRST_ = 2;
        /**
         * Controls whether an extra case level (positioned before the third level) is generated or not. Acceptable
         * values are OFF (default), when case level is not generated, and ON which causes the case level to be
         * generated. Contents of the case level are affected by the value of CASE_FIRST attribute. A simple way to
         * ignore accent differences in a string is to set the strength to PRIMARY and enable case level.
         */
        static final int CASE_LEVEL_ = 3;
        /**
         * Controls whether the normalization check and necessary normalizations are performed. When set to OFF
         * (default) no normalization check is performed. The correctness of the result is guaranteed only if the input
         * data is in so-called FCD form (see users manual for more info). When set to ON, an incremental check is
         * performed to see whether the input data is in the FCD form. If the data is not in the FCD form, incremental
         * NFD normalization is performed.
         */
        static final int NORMALIZATION_MODE_ = 4;
        /**
         * The strength attribute. Can be either PRIMARY, SECONDARY, TERTIARY, QUATERNARY or IDENTICAL. The usual
         * strength for most locales (except Japanese) is tertiary. Quaternary strength is useful when combined with
         * shifted setting for alternate handling attribute and for JIS x 4061 collation, when it is used to distinguish
         * between Katakana and Hiragana (this is achieved by setting the HIRAGANA_QUATERNARY mode to on. Otherwise,
         * quaternary level is affected only by the number of non ignorable code points in the string. Identical
         * strength is rarely useful, as it amounts to codepoints of the NFD form of the string.
         */
        static final int STRENGTH_ = 5;
        /**
         * When turned on, this attribute positions Hiragana before all non-ignorables on quaternary level. This is a
         * sneaky way to produce JIS sort order.
         */
        static final int HIRAGANA_QUATERNARY_MODE_ = 6;
        /**
         * Attribute count
         */
        static final int LIMIT_ = 7;
    }

    /**
     * DataManipulate singleton
     */
    static class DataManipulate implements Trie.DataManipulate {
        // public methods ----------------------------------------------------

        /**
         * Internal method called to parse a lead surrogate's ce for the offset to the next trail surrogate data.
         * 
         * @param ce
         *            collation element of the lead surrogate
         * @return data offset or 0 for the next trail surrogate
         * @stable ICU 2.8
         */
        public final int getFoldingOffset(int ce) {
            if (isSpecial(ce) && getTag(ce) == CE_SURROGATE_TAG_) {
                return (ce & 0xFFFFFF);
            }
            return 0;
        }

        /**
         * Get singleton object
         */
        public static final DataManipulate getInstance() {
            if (m_instance_ == null) {
                m_instance_ = new DataManipulate();
            }
            return m_instance_;
        }

        // private data member ----------------------------------------------

        /**
         * Singleton instance
         */
        private static DataManipulate m_instance_;

        // private constructor ----------------------------------------------

        /**
         * private to prevent initialization
         */
        private DataManipulate() {
        }
    }

    /**
     * UCAConstants
     */
    static final class UCAConstants {
        int FIRST_TERTIARY_IGNORABLE_[] = new int[2]; // 0x00000000
        int LAST_TERTIARY_IGNORABLE_[] = new int[2]; // 0x00000000
        int FIRST_PRIMARY_IGNORABLE_[] = new int[2]; // 0x00008705
        int FIRST_SECONDARY_IGNORABLE_[] = new int[2]; // 0x00000000
        int LAST_SECONDARY_IGNORABLE_[] = new int[2]; // 0x00000500
        int LAST_PRIMARY_IGNORABLE_[] = new int[2]; // 0x0000DD05
        int FIRST_VARIABLE_[] = new int[2]; // 0x05070505
        int LAST_VARIABLE_[] = new int[2]; // 0x13CF0505
        int FIRST_NON_VARIABLE_[] = new int[2]; // 0x16200505
        int LAST_NON_VARIABLE_[] = new int[2]; // 0x767C0505
        int RESET_TOP_VALUE_[] = new int[2]; // 0x9F000303
        int FIRST_IMPLICIT_[] = new int[2];
        int LAST_IMPLICIT_[] = new int[2];
        int FIRST_TRAILING_[] = new int[2];
        int LAST_TRAILING_[] = new int[2];
        int PRIMARY_TOP_MIN_;
        int PRIMARY_IMPLICIT_MIN_; // 0xE8000000
        int PRIMARY_IMPLICIT_MAX_; // 0xF0000000
        int PRIMARY_TRAILING_MIN_; // 0xE8000000
        int PRIMARY_TRAILING_MAX_; // 0xF0000000
        int PRIMARY_SPECIAL_MIN_; // 0xE8000000
        int PRIMARY_SPECIAL_MAX_; // 0xF0000000
    }

    /**
     * Script to Lead Byte and Lead Byte to Script Data
     * 
     */
    static final class LeadByteConstants {
        private static final int DATA_MASK_FOR_INDEX = 0x8000;
        private static final int[] EMPTY_INT_ARRAY = new int[0];

        private int serializedSize = 0;

        private Map<Integer, Integer> SCRIPT_TO_LEAD_BYTES_INDEX;
        private byte[] SCRIPT_TO_LEAD_BYTES_DATA;

        private int[] LEAD_BYTE_TO_SCRIPTS_INDEX;
        private byte[] LEAD_BYTE_TO_SCRIPTS_DATA;

        LeadByteConstants() {
        }

        void read(DataInputStream dis) throws IOException {
            int readcount = 0;
            int indexCount;
            int dataSize;

            // script to lead bytes
            indexCount = dis.readShort();
            readcount += 2;
            dataSize = dis.readShort();
            readcount += 2;
            this.SCRIPT_TO_LEAD_BYTES_INDEX = new HashMap<Integer, Integer>();
            //System.out.println("Script to Lead Bytes Index - Count = " + indexCount);
            for (int index = 0; index < indexCount; index++) {
                int reorderCode = dis.readShort(); // reorder code
                readcount += 2;
                int dataOffset = 0xffff & dis.readShort(); // data offset
                readcount += 2;
                //                 System.out.println("\t-------------");
                //                 System.out.println("\toffset = " + Integer.toHexString(readcount - 4));
                //                 System.out.println("\treorderCode = " + Integer.toHexString(reorderCode));
                //                 System.out.println("\tdataOffset = " + Integer.toHexString(dataOffset));
                this.SCRIPT_TO_LEAD_BYTES_INDEX.put(reorderCode, dataOffset);
            }

            this.SCRIPT_TO_LEAD_BYTES_DATA = new byte[dataSize * 2];
            dis.readFully(this.SCRIPT_TO_LEAD_BYTES_DATA, 0, this.SCRIPT_TO_LEAD_BYTES_DATA.length);
            readcount += this.SCRIPT_TO_LEAD_BYTES_DATA.length;

            // lead byte to scripts
            indexCount = dis.readShort();
            readcount += 2;
            dataSize = dis.readShort();
            readcount += 2;
            this.LEAD_BYTE_TO_SCRIPTS_INDEX = new int[indexCount];
            //System.out.println("Lead Byte to Scripts Index - Count = " + indexCount);
            for (int index = 0; index < indexCount; index++) {
                this.LEAD_BYTE_TO_SCRIPTS_INDEX[index] = 0xffff & dis.readShort();
                readcount += 2;
                //                System.out.println("\t-------------");
                //                System.out.println("\toffset = " + Integer.toHexString(readcount - 2));
                //                System.out.println("\tindex = " + Integer.toHexString(index));
                //                System.out.println("\tdataOffset = " + Integer.toHexString(this.LEAD_BYTE_TO_SCRIPTS_INDEX[index]));
            }

            this.LEAD_BYTE_TO_SCRIPTS_DATA = new byte[dataSize * 2];
            dis.readFully(this.LEAD_BYTE_TO_SCRIPTS_DATA, 0, this.LEAD_BYTE_TO_SCRIPTS_DATA.length);
            readcount += this.LEAD_BYTE_TO_SCRIPTS_DATA.length;

            this.serializedSize = readcount;
        }

        int getSerializedDataSize() {
            return this.serializedSize;
        }

        int[] getReorderCodesForLeadByte(int leadByte) {
            if (leadByte >= this.LEAD_BYTE_TO_SCRIPTS_INDEX.length) {
                return EMPTY_INT_ARRAY;
            }
            int offset = this.LEAD_BYTE_TO_SCRIPTS_INDEX[leadByte];
            if (offset == 0) {
                return EMPTY_INT_ARRAY;
            }
            int[] reorderCodes;
            if ((offset & DATA_MASK_FOR_INDEX) == DATA_MASK_FOR_INDEX) {
                reorderCodes = new int[1];
                reorderCodes[0] = offset & ~DATA_MASK_FOR_INDEX;
            } else {

                int length = readShort(this.LEAD_BYTE_TO_SCRIPTS_DATA, offset);
                offset++;

                reorderCodes = new int[length];
                for (int code = 0; code < length; code++, offset++) {
                    reorderCodes[code] = readShort(this.LEAD_BYTE_TO_SCRIPTS_DATA, offset);
                }
            }
            return reorderCodes;
        }

        int[] getLeadBytesForReorderCode(int reorderCode) {
            if (!this.SCRIPT_TO_LEAD_BYTES_INDEX.containsKey(reorderCode)) {
                return EMPTY_INT_ARRAY;
            }
            int offset = this.SCRIPT_TO_LEAD_BYTES_INDEX.get(reorderCode);

            if (offset == 0) {
                return EMPTY_INT_ARRAY;
            }
            
            int[] leadBytes;
            if ((offset & DATA_MASK_FOR_INDEX) == DATA_MASK_FOR_INDEX) {
                leadBytes = new int[1];
                leadBytes[0] = offset & ~DATA_MASK_FOR_INDEX;
            } else {

                int length = readShort(this.SCRIPT_TO_LEAD_BYTES_DATA, offset);
                offset++;

                leadBytes = new int[length];
                for (int leadByte = 0; leadByte < length; leadByte++, offset++) {
                    leadBytes[leadByte] = readShort(this.SCRIPT_TO_LEAD_BYTES_DATA, offset);
                }
            }
            return leadBytes;
        }

        private static int readShort(byte[] data, int offset) {
            return (0xff & data[offset * 2]) << 8 | (data[offset * 2 + 1] & 0xff);
        }
    }

    // package private data member -------------------------------------------

    static final byte BYTE_FIRST_TAILORED_ = (byte) 0x04;
    static final byte BYTE_COMMON_ = (byte) 0x05;
    static final int COMMON_TOP_2_ = 0x86; // int for unsigness
    static final int COMMON_BOTTOM_2_ = BYTE_COMMON_;
    static final int COMMON_BOTTOM_3 = 0x05;
    /**
     * Case strength mask
     */
    static final int CE_CASE_BIT_MASK_ = 0xC0;
    static final int CE_TAG_SHIFT_ = 24;
    static final int CE_TAG_MASK_ = 0x0F000000;

    static final int CE_SPECIAL_FLAG_ = 0xF0000000;
    /**
     * Lead surrogate that is tailored and doesn't start a contraction
     */
    static final int CE_SURROGATE_TAG_ = 5;
    /**
     * Mask to get the primary strength of the collation element
     */
    static final int CE_PRIMARY_MASK_ = 0xFFFF0000;
    /**
     * Mask to get the secondary strength of the collation element
     */
    static final int CE_SECONDARY_MASK_ = 0xFF00;
    /**
     * Mask to get the tertiary strength of the collation element
     */
    static final int CE_TERTIARY_MASK_ = 0xFF;
    /**
     * Primary strength shift
     */
    static final int CE_PRIMARY_SHIFT_ = 16;
    /**
     * Secondary strength shift
     */
    static final int CE_SECONDARY_SHIFT_ = 8;
    /**
     * Continuation marker
     */
    static final int CE_CONTINUATION_MARKER_ = 0xC0;

    /**
     * Size of collator raw data headers and options before the expansion data. This is used when expansion ces are to
     * be retrieved. ICU4C uses the expansion offset starting from UCollator.UColHeader, hence ICU4J will have to minus
     * that off to get the right expansion ce offset. In number of ints.
     */
    int m_expansionOffset_;
    /**
     * Size of collator raw data headers, options and expansions before contraction data. This is used when contraction
     * ces are to be retrieved. ICU4C uses contraction offset starting from UCollator.UColHeader, hence ICU4J will have
     * to minus that off to get the right contraction ce offset. In number of chars.
     */
    int m_contractionOffset_;
    /**
     * Flag indicator if Jamo is special
     */
    boolean m_isJamoSpecial_;

    // Collator options ------------------------------------------------------

    int m_defaultVariableTopValue_;
    boolean m_defaultIsFrenchCollation_;
    boolean m_defaultIsAlternateHandlingShifted_;
    int m_defaultCaseFirst_;
    boolean m_defaultIsCaseLevel_;
    int m_defaultDecomposition_;
    int m_defaultStrength_;
    boolean m_defaultIsHiragana4_;
    boolean m_defaultIsNumericCollation_;
    int[] m_defaultReorderCodes_;

    /**
     * Value of the variable top
     */
    int m_variableTopValue_;
    /**
     * Attribute for special Hiragana
     */
    boolean m_isHiragana4_;
    /**
     * Case sorting customization
     */
    int m_caseFirst_;
    /**
     * Numeric collation option
     */
    boolean m_isNumericCollation_;
    /**
     * Script order
     */
    int[] m_reorderCodes_;

    // end Collator options --------------------------------------------------

    /**
     * Expansion table
     */
    int m_expansion_[];
    /**
     * Contraction index table
     */
    char m_contractionIndex_[];
    /**
     * Contraction CE table
     */
    int m_contractionCE_[];
    /**
     * Data trie
     */
    IntTrie m_trie_;
    /**
     * Table to store all collation elements that are the last element of an expansion. This is for use in StringSearch.
     */
    int m_expansionEndCE_[];
    /**
     * Table to store the maximum size of any expansions that end with the corresponding collation element in
     * m_expansionEndCE_. For use in StringSearch too
     */
    byte m_expansionEndCEMaxSize_[];
    /**
     * Heuristic table to store information on whether a char character is considered "unsafe". "Unsafe" character are
     * combining marks or those belonging to some contraction sequence from the offset 1 onwards. E.g. if "ABC" is the
     * only contraction, then 'B' and 'C' are considered unsafe. If we have another contraction "ZA" with the one above,
     * then 'A', 'B', 'C' are "unsafe" but 'Z' is not.
     */
    byte m_unsafe_[];
    /**
     * Table to store information on whether a codepoint can occur as the last character in a contraction
     */
    byte m_contractionEnd_[];
    /**
     * Original collation rules
     */
    String m_rules_;
    /**
     * The smallest "unsafe" codepoint
     */
    char m_minUnsafe_;
    /**
     * The smallest codepoint that could be the end of a contraction
     */
    char m_minContractionEnd_;
    /**
     * General version of the collator
     */
    VersionInfo m_version_;
    /**
     * UCA version
     */
    VersionInfo m_UCA_version_;
    /**
     * UCD version
     */
    VersionInfo m_UCD_version_;
    /**
     * Lead byte and script data
     */
    int m_leadByteToScripts;
    int m_scriptToLeadBytes;
    /**
     * UnicodeData.txt property object
     */
    static final RuleBasedCollator UCA_;
    /**
     * UCA Constants
     */
    static final UCAConstants UCA_CONSTANTS_;
    /**
     * Lead Byte Constants
     */
    static LeadByteConstants LEADBYTE_CONSTANTS_;
    /**
     * Table for UCA and builder use
     */
    static final char UCA_CONTRACTIONS_[];

    private static boolean UCA_INIT_COMPLETE;

    /**
     * Implicit generator
     */
    static final ImplicitCEGenerator impCEGen_;

    static final byte SORT_LEVEL_TERMINATOR_ = 1;

    // These are values from UCA required for
    // implicit generation and supressing sort key compression
    // they should regularly be in the UCA, but if one
    // is running without UCA, it could be a problem
    static final int maxRegularPrimary = 0x7A;
    static final int minImplicitPrimary = 0xE0;
    static final int maxImplicitPrimary = 0xE4;

    // block to initialise character property database
    static {
        // take pains to let static class init succeed, otherwise the class itself won't exist and
        // clients will get a NoClassDefFoundException. Instead, make the constructors fail if
        // we can't load the UCA data.

        RuleBasedCollator iUCA_ = null;
        UCAConstants iUCA_CONSTANTS_ = null;
        LeadByteConstants iLEADBYTE_CONSTANTS = null;
        char iUCA_CONTRACTIONS_[] = null;
        ImplicitCEGenerator iimpCEGen_ = null;
        try {
            // !!! note what's going on here...
            // even though the static init of the class is not yet complete, we
            // instantiate an instance of the class. So we'd better be sure that
            // instantiation doesn't rely on the static initialization that's
            // not complete yet!
            iUCA_ = new RuleBasedCollator();
            iUCA_CONSTANTS_ = new UCAConstants();
            iLEADBYTE_CONSTANTS = new LeadByteConstants();
            iUCA_CONTRACTIONS_ = CollatorReader.read(iUCA_, iUCA_CONSTANTS_, iLEADBYTE_CONSTANTS);

            // called before doing canonical closure for the UCA.
            iimpCEGen_ = new ImplicitCEGenerator(minImplicitPrimary, maxImplicitPrimary);
            // iimpCEGen_ = new ImplicitCEGenerator(iUCA_CONSTANTS_.PRIMARY_IMPLICIT_MIN_,
            // iUCA_CONSTANTS_.PRIMARY_IMPLICIT_MAX_);
            iUCA_.init();
            ICUResourceBundle rb = (ICUResourceBundle) UResourceBundle.getBundleInstance(
                    ICUResourceBundle.ICU_COLLATION_BASE_NAME, ULocale.ENGLISH);
            iUCA_.m_rules_ = (String) rb.getObject("UCARules");
        } catch (MissingResourceException ex) {
            // throw ex;
        } catch (IOException e) {
            // e.printStackTrace();
            // throw new MissingResourceException(e.getMessage(),"","");
        }

        UCA_ = iUCA_;
        UCA_CONSTANTS_ = iUCA_CONSTANTS_;
        LEADBYTE_CONSTANTS_ = iLEADBYTE_CONSTANTS;
        UCA_CONTRACTIONS_ = iUCA_CONTRACTIONS_;
        impCEGen_ = iimpCEGen_;

        UCA_INIT_COMPLETE = true;
    }

    private static void checkUCA() throws MissingResourceException {
        if (UCA_INIT_COMPLETE && UCA_ == null) {
            throw new MissingResourceException("Collator UCA data unavailable", "", "");
        }
    }

    // package private constructors ------------------------------------------

    /**
     * <p>
     * Private contructor for use by subclasses. Public access to creating Collators is handled by the API
     * Collator.getInstance() or RuleBasedCollator(String rules).
     * </p>
     * <p>
     * This constructor constructs the UCA collator internally
     * </p>
     */
    RuleBasedCollator() {
        checkUCA();
        initUtility(false);
    }

    /**
     * Constructors a RuleBasedCollator from the argument locale. If no resource bundle is associated with the locale,
     * UCA is used instead.
     * 
     * @param locale
     */
    RuleBasedCollator(ULocale locale) {
        checkUCA();
        ICUResourceBundle rb = (ICUResourceBundle) UResourceBundle.getBundleInstance(
                ICUResourceBundle.ICU_COLLATION_BASE_NAME, locale);
        initUtility(false);
        if (rb != null) {
            try {
                // Use keywords, if supplied for lookup
                String collkey = locale.getKeywordValue("collation");
                if (collkey == null) {
                    collkey = rb.getStringWithFallback("collations/default");
                }

                // collations/default will always give a string back
                // keyword for the real collation data
                // if "collations/collkey" will return null if collkey == null
                ICUResourceBundle elements = rb.getWithFallback("collations/" + collkey);
                if (elements != null) {
                    // TODO: Determine actual & valid locale correctly
                    ULocale uloc = rb.getULocale();
                    setLocale(uloc, uloc);

                    m_rules_ = elements.getString("Sequence");
                    ByteBuffer buf = elements.get("%%CollationBin").getBinary();
                    // %%CollationBin
                    if (buf != null) {
                        // m_rules_ = (String)rules[1][1];
                        CollatorReader.initRBC(this, buf);
                        /*
                         * BufferedInputStream input = new BufferedInputStream( new ByteArrayInputStream(map)); /*
                         * CollatorReader reader = new CollatorReader(input, false); if (map.length >
                         * MIN_BINARY_DATA_SIZE_) { reader.read(this, null); } else { reader.readHeader(this);
                         * reader.readOptions(this); // duplicating UCA_'s data setWithUCATables(); }
                         */
                        // at this point, we have read in the collator
                        // now we need to check whether the binary image has
                        // the right UCA and other versions
                        if (!m_UCA_version_.equals(UCA_.m_UCA_version_) || !m_UCD_version_.equals(UCA_.m_UCD_version_)) {
                            init(m_rules_);
                            return;
                        }
                        try {
                        UResourceBundle reorderRes = elements.get("%%ReorderCodes");
                        if (reorderRes != null) {
                            int[] reorderCodes = reorderRes.getIntVector();
                            setReorderCodes(reorderCodes);
                            m_defaultReorderCodes_ = reorderCodes.clone();
                        }
                        } catch (MissingResourceException e) {
                            // ignore
                        }
                        init();
                        return;
                    } else {
                        init(m_rules_);
                        return;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                // if failed use UCA.
            }
        }
        setWithUCAData();
    }

    // package private methods -----------------------------------------------

    /**
     * Sets this collator to use the tables in UCA. Note options not taken care of here.
     */
    final void setWithUCATables() {
        m_contractionOffset_ = UCA_.m_contractionOffset_;
        m_expansionOffset_ = UCA_.m_expansionOffset_;
        m_expansion_ = UCA_.m_expansion_;
        m_contractionIndex_ = UCA_.m_contractionIndex_;
        m_contractionCE_ = UCA_.m_contractionCE_;
        m_trie_ = UCA_.m_trie_;
        m_expansionEndCE_ = UCA_.m_expansionEndCE_;
        m_expansionEndCEMaxSize_ = UCA_.m_expansionEndCEMaxSize_;
        m_unsafe_ = UCA_.m_unsafe_;
        m_contractionEnd_ = UCA_.m_contractionEnd_;
        m_minUnsafe_ = UCA_.m_minUnsafe_;
        m_minContractionEnd_ = UCA_.m_minContractionEnd_;
    }

    /**
     * Sets this collator to use the all options and tables in UCA.
     */
    final void setWithUCAData() {
        latinOneFailed_ = true;

        m_addition3_ = UCA_.m_addition3_;
        m_bottom3_ = UCA_.m_bottom3_;
        m_bottomCount3_ = UCA_.m_bottomCount3_;
        m_caseFirst_ = UCA_.m_caseFirst_;
        m_caseSwitch_ = UCA_.m_caseSwitch_;
        m_common3_ = UCA_.m_common3_;
        m_contractionOffset_ = UCA_.m_contractionOffset_;
        setDecomposition(UCA_.getDecomposition());
        m_defaultCaseFirst_ = UCA_.m_defaultCaseFirst_;
        m_defaultDecomposition_ = UCA_.m_defaultDecomposition_;
        m_defaultIsAlternateHandlingShifted_ = UCA_.m_defaultIsAlternateHandlingShifted_;
        m_defaultIsCaseLevel_ = UCA_.m_defaultIsCaseLevel_;
        m_defaultIsFrenchCollation_ = UCA_.m_defaultIsFrenchCollation_;
        m_defaultIsHiragana4_ = UCA_.m_defaultIsHiragana4_;
        m_defaultStrength_ = UCA_.m_defaultStrength_;
        m_defaultVariableTopValue_ = UCA_.m_defaultVariableTopValue_;
        m_defaultIsNumericCollation_ = UCA_.m_defaultIsNumericCollation_;
        m_expansionOffset_ = UCA_.m_expansionOffset_;
        m_isAlternateHandlingShifted_ = UCA_.m_isAlternateHandlingShifted_;
        m_isCaseLevel_ = UCA_.m_isCaseLevel_;
        m_isFrenchCollation_ = UCA_.m_isFrenchCollation_;
        m_isHiragana4_ = UCA_.m_isHiragana4_;
        m_isJamoSpecial_ = UCA_.m_isJamoSpecial_;
        m_isSimple3_ = UCA_.m_isSimple3_;
        m_mask3_ = UCA_.m_mask3_;
        m_minContractionEnd_ = UCA_.m_minContractionEnd_;
        m_minUnsafe_ = UCA_.m_minUnsafe_;
        m_rules_ = UCA_.m_rules_;
        setStrength(UCA_.getStrength());
        m_top3_ = UCA_.m_top3_;
        m_topCount3_ = UCA_.m_topCount3_;
        m_variableTopValue_ = UCA_.m_variableTopValue_;
        m_isNumericCollation_ = UCA_.m_isNumericCollation_;
        setWithUCATables();
        latinOneFailed_ = false;
    }

    /**
     * Test whether a char character is potentially "unsafe" for use as a collation starting point. "Unsafe" characters
     * are combining marks or those belonging to some contraction sequence from the offset 1 onwards. E.g. if "ABC" is
     * the only contraction, then 'B' and 'C' are considered unsafe. If we have another contraction "ZA" with the one
     * above, then 'A', 'B', 'C' are "unsafe" but 'Z' is not.
     * 
     * @param ch
     *            character to determin
     * @return true if ch is unsafe, false otherwise
     */
    final boolean isUnsafe(char ch) {
        if (ch < m_minUnsafe_) {
            return false;
        }

        if (ch >= (HEURISTIC_SIZE_ << HEURISTIC_SHIFT_)) {
            if (UTF16.isLeadSurrogate(ch) || UTF16.isTrailSurrogate(ch)) {
                // Trail surrogate are always considered unsafe.
                return true;
            }
            ch &= HEURISTIC_OVERFLOW_MASK_;
            ch += HEURISTIC_OVERFLOW_OFFSET_;
        }
        int value = m_unsafe_[ch >> HEURISTIC_SHIFT_];
        return ((value >> (ch & HEURISTIC_MASK_)) & 1) != 0;
    }

    /**
     * Approximate determination if a char character is at a contraction end. Guaranteed to be true if a character is at
     * the end of a contraction, otherwise it is not deterministic.
     * 
     * @param ch
     *            character to be determined
     */
    final boolean isContractionEnd(char ch) {
        if (UTF16.isTrailSurrogate(ch)) {
            return true;
        }

        if (ch < m_minContractionEnd_) {
            return false;
        }

        if (ch >= (HEURISTIC_SIZE_ << HEURISTIC_SHIFT_)) {
            ch &= HEURISTIC_OVERFLOW_MASK_;
            ch += HEURISTIC_OVERFLOW_OFFSET_;
        }
        int value = m_contractionEnd_[ch >> HEURISTIC_SHIFT_];
        return ((value >> (ch & HEURISTIC_MASK_)) & 1) != 0;
    }

    /**
     * Retrieve the tag of a special ce
     * 
     * @param ce
     *            ce to test
     * @return tag of ce
     */
    static int getTag(int ce) {
        return (ce & CE_TAG_MASK_) >> CE_TAG_SHIFT_;
    }

    /**
     * Checking if ce is special
     * 
     * @param ce
     *            to check
     * @return true if ce is special
     */
    static boolean isSpecial(int ce) {
        return (ce & CE_SPECIAL_FLAG_) == CE_SPECIAL_FLAG_;
    }

    /**
     * Checks if the argument ce is a continuation
     * 
     * @param ce
     *            collation element to test
     * @return true if ce is a continuation
     */
    static final boolean isContinuation(int ce) {
        return ce != CollationElementIterator.NULLORDER && (ce & CE_CONTINUATION_TAG_) == CE_CONTINUATION_TAG_;
    }

    // private inner classes ------------------------------------------------

    // private variables -----------------------------------------------------

    /**
     * The smallest natural unsafe or contraction end char character before tailoring. This is a combining mark.
     */
    private static final int DEFAULT_MIN_HEURISTIC_ = 0x300;
    /**
     * Heuristic table table size. Size is 32 bytes, 1 bit for each latin 1 char, and some power of two for hashing the
     * rest of the chars. Size in bytes.
     */
    private static final char HEURISTIC_SIZE_ = 1056;
    /**
     * Mask value down to "some power of two" - 1, number of bits, not num of bytes.
     */
    private static final char HEURISTIC_OVERFLOW_MASK_ = 0x1fff;
    /**
     * Unsafe character shift
     */
    private static final int HEURISTIC_SHIFT_ = 3;
    /**
     * Unsafe character addition for character too large, it has to be folded then incremented.
     */
    private static final char HEURISTIC_OVERFLOW_OFFSET_ = 256;
    /**
     * Mask value to get offset in heuristic table.
     */
    private static final char HEURISTIC_MASK_ = 7;

    private int m_caseSwitch_;
    private int m_common3_;
    private int m_mask3_;
    /**
     * When switching case, we need to add or subtract different values.
     */
    private int m_addition3_;
    /**
     * Upper range when compressing
     */
    private int m_top3_;
    /**
     * Upper range when compressing
     */
    private int m_bottom3_;
    private int m_topCount3_;
    private int m_bottomCount3_;
    /**
     * Script reordering table
     */
    private byte[] m_leadBytePermutationTable_;
    /**
     * Case first constants
     */
    private static final int CASE_SWITCH_ = 0xC0;
    private static final int NO_CASE_SWITCH_ = 0;
    /**
     * Case level constants
     */
    private static final int CE_REMOVE_CASE_ = 0x3F;
    private static final int CE_KEEP_CASE_ = 0xFF;
    /**
     * Case strength mask
     */
    private static final int CE_CASE_MASK_3_ = 0xFF;
    /**
     * Sortkey size factor. Values can be changed.
     */
    private static final double PROPORTION_2_ = 0.5;
    private static final double PROPORTION_3_ = 0.667;

    // These values come from the UCA ----------------------------------------

    /**
     * This is an enum that lists magic special byte values from the fractional UCA
     */
    // private static final byte BYTE_ZERO_ = 0x0;
    // private static final byte BYTE_LEVEL_SEPARATOR_ = (byte)0x01;
    // private static final byte BYTE_SORTKEY_GLUE_ = (byte)0x02;
    private static final byte BYTE_SHIFT_PREFIX_ = (byte) 0x03;
    /* private */static final byte BYTE_UNSHIFTED_MIN_ = BYTE_SHIFT_PREFIX_;
    // private static final byte BYTE_FIRST_UCA_ = BYTE_COMMON_;
    // TODO: Make the following values dynamic since they change with almost every UCA version.
    static final byte CODAN_PLACEHOLDER = 0x12;
    private static final byte BYTE_FIRST_NON_LATIN_PRIMARY_ = (byte) 0x5B;

    private static final byte BYTE_UNSHIFTED_MAX_ = (byte) 0xFF;
    private static final int TOTAL_2_ = COMMON_TOP_2_ - COMMON_BOTTOM_2_ - 1;
    private static final int FLAG_BIT_MASK_CASE_SWITCH_OFF_ = 0x80;
    private static final int FLAG_BIT_MASK_CASE_SWITCH_ON_ = 0x40;
    private static final int COMMON_TOP_CASE_SWITCH_OFF_3_ = 0x85;
    private static final int COMMON_TOP_CASE_SWITCH_LOWER_3_ = 0x45;
    private static final int COMMON_TOP_CASE_SWITCH_UPPER_3_ = 0xC5;
    private static final int COMMON_BOTTOM_3_ = 0x05;
    private static final int COMMON_BOTTOM_CASE_SWITCH_UPPER_3_ = 0x86;
    private static final int COMMON_BOTTOM_CASE_SWITCH_LOWER_3_ = COMMON_BOTTOM_3_;
    private static final int TOP_COUNT_2_ = (int) (PROPORTION_2_ * TOTAL_2_);
    private static final int BOTTOM_COUNT_2_ = TOTAL_2_ - TOP_COUNT_2_;
    private static final int COMMON_2_ = COMMON_BOTTOM_2_;
    private static final int COMMON_UPPER_FIRST_3_ = 0xC5;
    private static final int COMMON_NORMAL_3_ = COMMON_BOTTOM_3_;
    // private static final int COMMON_4_ = (byte)0xFF;

    /*
     * Minimum size required for the binary collation data in bytes. Size of UCA header + size of options to 4 bytes
     */
    // private static final int MIN_BINARY_DATA_SIZE_ = (42 + 25) << 2;

    /**
     * If this collator is to generate only simple tertiaries for fast path
     */
    private boolean m_isSimple3_;

    /**
     * French collation sorting flag
     */
    private boolean m_isFrenchCollation_;
    /**
     * Flag indicating if shifted is requested for Quaternary alternate handling. If this is not true, the default for
     * alternate handling will be non-ignorable.
     */
    private boolean m_isAlternateHandlingShifted_;
    /**
     * Extra case level for sorting
     */
    private boolean m_isCaseLevel_;

    private static final int SORT_BUFFER_INIT_SIZE_ = 128;
    private static final int SORT_BUFFER_INIT_SIZE_1_ = SORT_BUFFER_INIT_SIZE_ << 3;
    private static final int SORT_BUFFER_INIT_SIZE_2_ = SORT_BUFFER_INIT_SIZE_;
    private static final int SORT_BUFFER_INIT_SIZE_3_ = SORT_BUFFER_INIT_SIZE_;
    private static final int SORT_BUFFER_INIT_SIZE_CASE_ = SORT_BUFFER_INIT_SIZE_ >> 2;
    private static final int SORT_BUFFER_INIT_SIZE_4_ = SORT_BUFFER_INIT_SIZE_;

    private static final int CE_CONTINUATION_TAG_ = 0xC0;
    private static final int CE_REMOVE_CONTINUATION_MASK_ = 0xFFFFFF3F;

    private static final int LAST_BYTE_MASK_ = 0xFF;

    // private static final int CE_RESET_TOP_VALUE_ = 0x9F000303;
    // private static final int CE_NEXT_TOP_VALUE_ = 0xE8960303;

    private static final byte SORT_CASE_BYTE_START_ = (byte) 0x80;
    private static final byte SORT_CASE_SHIFT_START_ = (byte) 7;

    /**
     * CE buffer size
     */
    private static final int CE_BUFFER_SIZE_ = 512;

    // variables for Latin-1 processing
    boolean latinOneUse_ = false;
    boolean latinOneRegenTable_ = false;
    boolean latinOneFailed_ = false;

    int latinOneTableLen_ = 0;
    int latinOneCEs_[] = null;
    /**
     * Bunch of utility iterators
     */
    private StringUCharacterIterator m_srcUtilIter_;
    private CollationElementIterator m_srcUtilColEIter_;
    private StringUCharacterIterator m_tgtUtilIter_;
    private CollationElementIterator m_tgtUtilColEIter_;
    /**
     * Utility comparison flags
     */
    private boolean m_utilCompare0_;
    // private boolean m_utilCompare1_;
    private boolean m_utilCompare2_;
    private boolean m_utilCompare3_;
    private boolean m_utilCompare4_;
    private boolean m_utilCompare5_;
    /**
     * Utility byte buffer
     */
    private byte m_utilBytes0_[];
    private byte m_utilBytes1_[];
    private byte m_utilBytes2_[];
    private byte m_utilBytes3_[];
    private byte m_utilBytes4_[];
    // private byte m_utilBytes5_[];
    private RawCollationKey m_utilRawCollationKey_;

    private int m_utilBytesCount0_;
    private int m_utilBytesCount1_;
    private int m_utilBytesCount2_;
    private int m_utilBytesCount3_;
    private int m_utilBytesCount4_;
    // private int m_utilBytesCount5_;
    // private int m_utilCount0_;
    // private int m_utilCount1_;
    private int m_utilCount2_;
    private int m_utilCount3_;
    private int m_utilCount4_;
    // private int m_utilCount5_;

    private int m_utilFrenchStart_;
    private int m_utilFrenchEnd_;

    /**
     * Preparing the CE buffers. will be filled during the primary phase
     */
    private int m_srcUtilCEBuffer_[];
    private int m_tgtUtilCEBuffer_[];
    private int m_srcUtilCEBufferSize_;
    private int m_tgtUtilCEBufferSize_;

    private int m_srcUtilContOffset_;
    private int m_tgtUtilContOffset_;

    private int m_srcUtilOffset_;
    private int m_tgtUtilOffset_;

    // private methods -------------------------------------------------------

    private void init(String rules) throws Exception {
        setWithUCAData();
        CollationParsedRuleBuilder builder = new CollationParsedRuleBuilder(rules);
        builder.setRules(this);
        m_rules_ = rules;
        init();
        buildPermutationTable();
        initUtility(false);
    }

    private final int compareRegular(String source, String target, int offset) {
        if (m_srcUtilIter_ == null) {
            initUtility(true);
        }
        int strength = getStrength();
        // setting up the collator parameters
        m_utilCompare0_ = m_isCaseLevel_;
        // m_utilCompare1_ = true;
        m_utilCompare2_ = strength >= SECONDARY;
        m_utilCompare3_ = strength >= TERTIARY;
        m_utilCompare4_ = strength >= QUATERNARY;
        m_utilCompare5_ = strength == IDENTICAL;
        boolean doFrench = m_isFrenchCollation_ && m_utilCompare2_;
        boolean doShift4 = m_isAlternateHandlingShifted_ && m_utilCompare4_;
        boolean doHiragana4 = m_isHiragana4_ && m_utilCompare4_;

        if (doHiragana4 && doShift4) {
            String sourcesub = source.substring(offset);
            String targetsub = target.substring(offset);
            return compareBySortKeys(sourcesub, targetsub);
        }

        // This is the lowest primary value that will not be ignored if shifted
        int lowestpvalue = m_isAlternateHandlingShifted_ ? m_variableTopValue_ << 16 : 0;
        m_srcUtilCEBufferSize_ = 0;
        m_tgtUtilCEBufferSize_ = 0;
        int result = doPrimaryCompare(doHiragana4, lowestpvalue, source, target, offset);
        if (m_srcUtilCEBufferSize_ == -1 && m_tgtUtilCEBufferSize_ == -1) {
            // since the cebuffer is cleared when we have determined that
            // either source is greater than target or vice versa, the return
            // result is the comparison result and not the hiragana result
            return result;
        }

        int hiraganaresult = result;

        if (m_utilCompare2_) {
            result = doSecondaryCompare(doFrench);
            if (result != 0) {
                return result;
            }
        }
        // doing the case bit
        if (m_utilCompare0_) {
            result = doCaseCompare();
            if (result != 0) {
                return result;
            }
        }
        // Tertiary level
        if (m_utilCompare3_) {
            result = doTertiaryCompare();
            if (result != 0) {
                return result;
            }
        }

        if (doShift4) { // checkQuad
            result = doQuaternaryCompare(lowestpvalue);
            if (result != 0) {
                return result;
            }
        } else if (doHiragana4 && hiraganaresult != 0) {
            // If we're fine on quaternaries, we might be different
            // on Hiragana. This, however, might fail us in shifted.
            return hiraganaresult;
        }

        // For IDENTICAL comparisons, we use a bitwise character comparison
        // as a tiebreaker if all else is equal.
        // Getting here should be quite rare - strings are not identical -
        // that is checked first, but compared == through all other checks.
        if (m_utilCompare5_) {
            return doIdenticalCompare(source, target, offset, true);
        }
        return 0;
    }

    // Is this primary weight compressible?
    // Returns false for multi-lead-byte scripts (digits, Latin, Han, implicit).
    // TODO: This should use per-lead-byte flags from FractionalUCA.txt.
    static boolean isCompressible(int primary1) {
        return BYTE_FIRST_NON_LATIN_PRIMARY_ <= primary1 && primary1 <= maxRegularPrimary;
    }

    /**
     * Gets the 2 bytes of primary order and adds it to the primary byte array
     * 
     * @param ce
     *            current ce
     * @param notIsContinuation
     *            flag indicating if the current bytes belong to a continuation ce
     * @param doShift
     *            flag indicating if ce is to be shifted
     * @param leadPrimary
     *            lead primary used for compression
     * @param commonBottom4
     *            common byte value for Quaternary
     * @param bottomCount4
     *            smallest byte value for Quaternary
     * @return the new lead primary for compression
     */
    private final int doPrimaryBytes(int ce, boolean notIsContinuation, boolean doShift, int leadPrimary,
            int commonBottom4, int bottomCount4) {

        int p2 = (ce >>>= 16) & LAST_BYTE_MASK_; // in ints for unsigned
        int p1 = ce >>> 8; // comparison
        int originalP1 = p1;
        if (notIsContinuation) {
            if (m_leadBytePermutationTable_ != null) {
                p1 = 0xff & m_leadBytePermutationTable_[p1];
            }
        }

        if (doShift) {
            if (m_utilCount4_ > 0) {
                while (m_utilCount4_ > bottomCount4) {
                    m_utilBytes4_ = append(m_utilBytes4_, m_utilBytesCount4_, (byte) (commonBottom4 + bottomCount4));
                    m_utilBytesCount4_++;
                    m_utilCount4_ -= bottomCount4;
                }
                m_utilBytes4_ = append(m_utilBytes4_, m_utilBytesCount4_, (byte) (commonBottom4 + (m_utilCount4_ - 1)));
                m_utilBytesCount4_++;
                m_utilCount4_ = 0;
            }
            // dealing with a variable and we're treating them as shifted
            // This is a shifted ignorable
            if (p1 != 0) {
                // we need to check this since we could be in continuation
                m_utilBytes4_ = append(m_utilBytes4_, m_utilBytesCount4_, (byte) p1);
                m_utilBytesCount4_++;
            }
            if (p2 != 0) {
                m_utilBytes4_ = append(m_utilBytes4_, m_utilBytesCount4_, (byte) p2);
                m_utilBytesCount4_++;
            }
        } else {
            // Note: This code assumes that the table is well built
            // i.e. not having 0 bytes where they are not supposed to be.
            // Usually, we'll have non-zero primary1 & primary2, except
            // in cases of LatinOne and friends, when primary2 will be
            // regular and simple sortkey calc
            if (p1 != CollationElementIterator.IGNORABLE) {
                if (notIsContinuation) {
                    if (leadPrimary == p1) {
                        m_utilBytes1_ = append(m_utilBytes1_, m_utilBytesCount1_, (byte) p2);
                        m_utilBytesCount1_++;
                    } else {
                        if (leadPrimary != 0) {
                            m_utilBytes1_ = append(m_utilBytes1_, m_utilBytesCount1_,
                                    ((p1 > leadPrimary) ? BYTE_UNSHIFTED_MAX_ : BYTE_UNSHIFTED_MIN_));
                            m_utilBytesCount1_++;
                        }
                        if (p2 == CollationElementIterator.IGNORABLE) {
                            // one byter, not compressed
                            m_utilBytes1_ = append(m_utilBytes1_, m_utilBytesCount1_, (byte) p1);
                            m_utilBytesCount1_++;
                            leadPrimary = 0;
                        } else if (isCompressible(originalP1)) {
                            // compress
                            leadPrimary = p1;
                            m_utilBytes1_ = append(m_utilBytes1_, m_utilBytesCount1_, (byte) p1);
                            m_utilBytesCount1_++;
                            m_utilBytes1_ = append(m_utilBytes1_, m_utilBytesCount1_, (byte) p2);
                            m_utilBytesCount1_++;
                        } else {
                            leadPrimary = 0;
                            m_utilBytes1_ = append(m_utilBytes1_, m_utilBytesCount1_, (byte) p1);
                            m_utilBytesCount1_++;
                            m_utilBytes1_ = append(m_utilBytes1_, m_utilBytesCount1_, (byte) p2);
                            m_utilBytesCount1_++;
                        }
                    }
                } else {
                    // continuation, add primary to the key, no compression
                    m_utilBytes1_ = append(m_utilBytes1_, m_utilBytesCount1_, (byte) p1);
                    m_utilBytesCount1_++;
                    if (p2 != CollationElementIterator.IGNORABLE) {
                        m_utilBytes1_ = append(m_utilBytes1_, m_utilBytesCount1_, (byte) p2);
                        // second part
                        m_utilBytesCount1_++;
                    }
                }
            }
        }
        return leadPrimary;
    }

    /**
     * Gets the secondary byte and adds it to the secondary byte array
     * 
     * @param ce
     *            current ce
     * @param notIsContinuation
     *            flag indicating if the current bytes belong to a continuation ce
     * @param doFrench
     *            flag indicator if french sort is to be performed
     */
    private final void doSecondaryBytes(int ce, boolean notIsContinuation, boolean doFrench) {
        int s = (ce >>= 8) & LAST_BYTE_MASK_; // int for comparison
        if (s != 0) {
            if (!doFrench) {
                // This is compression code.
                if (s == COMMON_2_ && notIsContinuation) {
                    m_utilCount2_++;
                } else {
                    if (m_utilCount2_ > 0) {
                        if (s > COMMON_2_) { // not necessary for 4th level.
                            while (m_utilCount2_ > TOP_COUNT_2_) {
                                m_utilBytes2_ = append(m_utilBytes2_, m_utilBytesCount2_,
                                        (byte) (COMMON_TOP_2_ - TOP_COUNT_2_));
                                m_utilBytesCount2_++;
                                m_utilCount2_ -= TOP_COUNT_2_;
                            }
                            m_utilBytes2_ = append(m_utilBytes2_, m_utilBytesCount2_,
                                    (byte) (COMMON_TOP_2_ - (m_utilCount2_ - 1)));
                            m_utilBytesCount2_++;
                        } else {
                            while (m_utilCount2_ > BOTTOM_COUNT_2_) {
                                m_utilBytes2_ = append(m_utilBytes2_, m_utilBytesCount2_,
                                        (byte) (COMMON_BOTTOM_2_ + BOTTOM_COUNT_2_));
                                m_utilBytesCount2_++;
                                m_utilCount2_ -= BOTTOM_COUNT_2_;
                            }
                            m_utilBytes2_ = append(m_utilBytes2_, m_utilBytesCount2_,
                                    (byte) (COMMON_BOTTOM_2_ + (m_utilCount2_ - 1)));
                            m_utilBytesCount2_++;
                        }
                        m_utilCount2_ = 0;
                    }
                    m_utilBytes2_ = append(m_utilBytes2_, m_utilBytesCount2_, (byte) s);
                    m_utilBytesCount2_++;
                }
            } else {
                m_utilBytes2_ = append(m_utilBytes2_, m_utilBytesCount2_, (byte) s);
                m_utilBytesCount2_++;
                // Do the special handling for French secondaries
                // We need to get continuation elements and do intermediate
                // restore
                // abc1c2c3de with french secondaries need to be edc1c2c3ba
                // NOT edc3c2c1ba
                if (notIsContinuation) {
                    if (m_utilFrenchStart_ != -1) {
                        // reverse secondaries from frenchStartPtr up to
                        // frenchEndPtr
                        reverseBuffer(m_utilBytes2_);
                        m_utilFrenchStart_ = -1;
                    }
                } else {
                    if (m_utilFrenchStart_ == -1) {
                        m_utilFrenchStart_ = m_utilBytesCount2_ - 2;
                    }
                    m_utilFrenchEnd_ = m_utilBytesCount2_ - 1;
                }
            }
        }
    }

    /**
     * Reverse the argument buffer
     * 
     * @param buffer
     *            to reverse
     */
    private void reverseBuffer(byte buffer[]) {
        int start = m_utilFrenchStart_;
        int end = m_utilFrenchEnd_;
        while (start < end) {
            byte b = buffer[start];
            buffer[start++] = buffer[end];
            buffer[end--] = b;
        }
    }

    /**
     * Insert the case shifting byte if required
     * 
     * @param caseshift
     *            value
     * @return new caseshift value
     */
    private final int doCaseShift(int caseshift) {
        if (caseshift == 0) {
            m_utilBytes0_ = append(m_utilBytes0_, m_utilBytesCount0_, SORT_CASE_BYTE_START_);
            m_utilBytesCount0_++;
            caseshift = SORT_CASE_SHIFT_START_;
        }
        return caseshift;
    }

    /**
     * Performs the casing sort
     * 
     * @param tertiary
     *            byte in ints for easy comparison
     * @param notIsContinuation
     *            flag indicating if the current bytes belong to a continuation ce
     * @param caseshift
     * @return the new value of case shift
     */
    private final int doCaseBytes(int tertiary, boolean notIsContinuation, int caseshift) {
        caseshift = doCaseShift(caseshift);

        if (notIsContinuation && tertiary != 0) {
            byte casebits = (byte) (tertiary & 0xC0);
            if (m_caseFirst_ == AttributeValue.UPPER_FIRST_) {
                if (casebits == 0) {
                    m_utilBytes0_[m_utilBytesCount0_ - 1] |= (1 << (--caseshift));
                } else {
                    // second bit
                    caseshift = doCaseShift(caseshift - 1);
                    m_utilBytes0_[m_utilBytesCount0_ - 1] |= ((casebits >> 6) & 1) << (--caseshift);
                }
            } else {
                if (casebits != 0) {
                    m_utilBytes0_[m_utilBytesCount0_ - 1] |= 1 << (--caseshift);
                    // second bit
                    caseshift = doCaseShift(caseshift);
                    m_utilBytes0_[m_utilBytesCount0_ - 1] |= ((casebits >> 7) & 1) << (--caseshift);
                } else {
                    caseshift--;
                }
            }
        }

        return caseshift;
    }

    /**
     * Gets the tertiary byte and adds it to the tertiary byte array
     * 
     * @param tertiary
     *            byte in int for easy comparison
     * @param notIsContinuation
     *            flag indicating if the current bytes belong to a continuation ce
     */
    private final void doTertiaryBytes(int tertiary, boolean notIsContinuation) {
        if (tertiary != 0) {
            // This is compression code.
            // sequence size check is included in the if clause
            if (tertiary == m_common3_ && notIsContinuation) {
                m_utilCount3_++;
            } else {
                int common3 = m_common3_ & LAST_BYTE_MASK_;
                if (tertiary > common3 && m_common3_ == COMMON_NORMAL_3_) {
                    tertiary += m_addition3_;
                } else if (tertiary <= common3 && m_common3_ == COMMON_UPPER_FIRST_3_) {
                    tertiary -= m_addition3_;
                }
                if (m_utilCount3_ > 0) {
                    if (tertiary > common3) {
                        while (m_utilCount3_ > m_topCount3_) {
                            m_utilBytes3_ = append(m_utilBytes3_, m_utilBytesCount3_, (byte) (m_top3_ - m_topCount3_));
                            m_utilBytesCount3_++;
                            m_utilCount3_ -= m_topCount3_;
                        }
                        m_utilBytes3_ = append(m_utilBytes3_, m_utilBytesCount3_,
                                (byte) (m_top3_ - (m_utilCount3_ - 1)));
                        m_utilBytesCount3_++;
                    } else {
                        while (m_utilCount3_ > m_bottomCount3_) {
                            m_utilBytes3_ = append(m_utilBytes3_, m_utilBytesCount3_,
                                    (byte) (m_bottom3_ + m_bottomCount3_));
                            m_utilBytesCount3_++;
                            m_utilCount3_ -= m_bottomCount3_;
                        }
                        m_utilBytes3_ = append(m_utilBytes3_, m_utilBytesCount3_,
                                (byte) (m_bottom3_ + (m_utilCount3_ - 1)));
                        m_utilBytesCount3_++;
                    }
                    m_utilCount3_ = 0;
                }
                m_utilBytes3_ = append(m_utilBytes3_, m_utilBytesCount3_, (byte) tertiary);
                m_utilBytesCount3_++;
            }
        }
    }

    /**
     * Gets the Quaternary byte and adds it to the Quaternary byte array
     * 
     * @param isCodePointHiragana
     *            flag indicator if the previous codepoint we dealt with was Hiragana
     * @param commonBottom4
     *            smallest common Quaternary byte
     * @param bottomCount4
     *            smallest Quaternary byte
     * @param hiragana4
     *            hiragana Quaternary byte
     */
    private final void doQuaternaryBytes(boolean isCodePointHiragana, int commonBottom4, int bottomCount4,
            byte hiragana4) {
        if (isCodePointHiragana) { // This was Hiragana, need to note it
            if (m_utilCount4_ > 0) { // Close this part
                while (m_utilCount4_ > bottomCount4) {
                    m_utilBytes4_ = append(m_utilBytes4_, m_utilBytesCount4_, (byte) (commonBottom4 + bottomCount4));
                    m_utilBytesCount4_++;
                    m_utilCount4_ -= bottomCount4;
                }
                m_utilBytes4_ = append(m_utilBytes4_, m_utilBytesCount4_, (byte) (commonBottom4 + (m_utilCount4_ - 1)));
                m_utilBytesCount4_++;
                m_utilCount4_ = 0;
            }
            m_utilBytes4_ = append(m_utilBytes4_, m_utilBytesCount4_, hiragana4); // Add the Hiragana
            m_utilBytesCount4_++;
        } else { // This wasn't Hiragana, so we can continue adding stuff
            m_utilCount4_++;
        }
    }

    /**
     * Iterates through the argument string for all ces. Split the ces into their relevant primaries, secondaries etc.
     * 
     * @param source
     *            normalized string
     * @param doFrench
     *            flag indicator if special handling of French has to be done
     * @param hiragana4
     *            offset for Hiragana quaternary
     * @param commonBottom4
     *            smallest common quaternary byte
     * @param bottomCount4
     *            smallest quaternary byte
     */
    private final void getSortKeyBytes(String source, boolean doFrench, byte hiragana4, int commonBottom4,
            int bottomCount4)

    {
        if (m_srcUtilIter_ == null) {
            initUtility(true);
        }
        int backupDecomposition = getDecomposition();
        setDecomposition(NO_DECOMPOSITION); // have to revert to backup later
        m_srcUtilIter_.setText(source);
        m_srcUtilColEIter_.setText(m_srcUtilIter_);
        m_utilFrenchStart_ = -1;
        m_utilFrenchEnd_ = -1;

        boolean doShift = false;
        boolean notIsContinuation = false;

        int leadPrimary = 0; // int for easier comparison
        int caseShift = 0;

        while (true) {
            int ce = m_srcUtilColEIter_.next();
            if (ce == CollationElementIterator.NULLORDER) {
                break;
            }

            if (ce == CollationElementIterator.IGNORABLE) {
                continue;
            }

            notIsContinuation = !isContinuation(ce);
            
            boolean isPrimaryByteIgnorable = (ce & CE_PRIMARY_MASK_) == 0;
            // actually we can just check that the first byte is 0
            // generation stuffs the order left first
            boolean isSmallerThanVariableTop = (ce >>> CE_PRIMARY_SHIFT_) <= m_variableTopValue_;
            doShift = (m_isAlternateHandlingShifted_
                    && ((notIsContinuation && isSmallerThanVariableTop && !isPrimaryByteIgnorable) // primary byte not 0
                            || (!notIsContinuation && doShift)) || (doShift && isPrimaryByteIgnorable));
            if (doShift && isPrimaryByteIgnorable) {
                // amendment to the UCA says that primary ignorables and other
                // ignorables should be removed if following a shifted code
                // point
                // if we were shifted and we got an ignorable code point
                // we should just completely ignore it
                continue;
            }
            leadPrimary = doPrimaryBytes(ce, notIsContinuation, doShift, leadPrimary, commonBottom4, bottomCount4);

            if (doShift) {
                continue;
            }
            if (m_utilCompare2_) {
                doSecondaryBytes(ce, notIsContinuation, doFrench);
            }

            int t = ce & LAST_BYTE_MASK_;
            if (!notIsContinuation) {
                t = ce & CE_REMOVE_CONTINUATION_MASK_;
            }

            if (m_utilCompare0_ && (!isPrimaryByteIgnorable || m_utilCompare2_)) {
                // do the case level if we need to do it. We don't want to calculate
                // case level for primary ignorables if we have only primary strength and case level
                // otherwise we would break well formedness of CEs
                caseShift = doCaseBytes(t, notIsContinuation, caseShift);
            } else if (notIsContinuation) {
                t ^= m_caseSwitch_;
            }

            t &= m_mask3_;

            if (m_utilCompare3_) {
                doTertiaryBytes(t, notIsContinuation);
            }

            if (m_utilCompare4_ && notIsContinuation) { // compare quad
                doQuaternaryBytes(m_srcUtilColEIter_.m_isCodePointHiragana_, commonBottom4, bottomCount4, hiragana4);
            }
        }
        setDecomposition(backupDecomposition); // reverts to original
        if (m_utilFrenchStart_ != -1) {
            // one last round of checks
            reverseBuffer(m_utilBytes2_);
        }
    }

    /**
     * From the individual strength byte results the final compact sortkey will be calculated.
     * 
     * @param source
     *            text string
     * @param doFrench
     *            flag indicating that special handling of French has to be done
     * @param commonBottom4
     *            smallest common quaternary byte
     * @param bottomCount4
     *            smallest quaternary byte
     * @param key
     *            output RawCollationKey to store results, key cannot be null
     */
    private final void getSortKey(String source, boolean doFrench, int commonBottom4, int bottomCount4,
            RawCollationKey key) {
        // we have done all the CE's, now let's put them together to form
        // a key
        if (m_utilCompare2_) {
            doSecondary(doFrench);
        }
        // adding case level should be independent of secondary level
        if (m_utilCompare0_) {
            doCase();
        }
        if (m_utilCompare3_) {
            doTertiary();
            if (m_utilCompare4_) {
                doQuaternary(commonBottom4, bottomCount4);
                if (m_utilCompare5_) {
                    doIdentical(source);
                }

            }
        }
        m_utilBytes1_ = append(m_utilBytes1_, m_utilBytesCount1_, (byte) 0);
        m_utilBytesCount1_++;

        key.set(m_utilBytes1_, 0, m_utilBytesCount1_);
    }

    /**
     * Packs the French bytes
     */
    private final void doFrench() {
        for (int i = 0; i < m_utilBytesCount2_; i++) {
            byte s = m_utilBytes2_[m_utilBytesCount2_ - i - 1];
            // This is compression code.
            if (s == COMMON_2_) {
                ++m_utilCount2_;
            } else {
                if (m_utilCount2_ > 0) {
                    // getting the unsigned value
                    if ((s & LAST_BYTE_MASK_) > COMMON_2_) {
                        // not necessary for 4th level.
                        while (m_utilCount2_ > TOP_COUNT_2_) {
                            m_utilBytes1_ = append(m_utilBytes1_, m_utilBytesCount1_,
                                    (byte) (COMMON_TOP_2_ - TOP_COUNT_2_));
                            m_utilBytesCount1_++;
                            m_utilCount2_ -= TOP_COUNT_2_;
                        }
                        m_utilBytes1_ = append(m_utilBytes1_, m_utilBytesCount1_,
                                (byte) (COMMON_TOP_2_ - (m_utilCount2_ - 1)));
                        m_utilBytesCount1_++;
                    } else {
                        while (m_utilCount2_ > BOTTOM_COUNT_2_) {
                            m_utilBytes1_ = append(m_utilBytes1_, m_utilBytesCount1_,
                                    (byte) (COMMON_BOTTOM_2_ + BOTTOM_COUNT_2_));
                            m_utilBytesCount1_++;
                            m_utilCount2_ -= BOTTOM_COUNT_2_;
                        }
                        m_utilBytes1_ = append(m_utilBytes1_, m_utilBytesCount1_,
                                (byte) (COMMON_BOTTOM_2_ + (m_utilCount2_ - 1)));
                        m_utilBytesCount1_++;
                    }
                    m_utilCount2_ = 0;
                }
                m_utilBytes1_ = append(m_utilBytes1_, m_utilBytesCount1_, s);
                m_utilBytesCount1_++;
            }
        }
        if (m_utilCount2_ > 0) {
            while (m_utilCount2_ > BOTTOM_COUNT_2_) {
                m_utilBytes1_ = append(m_utilBytes1_, m_utilBytesCount1_, (byte) (COMMON_BOTTOM_2_ + BOTTOM_COUNT_2_));
                m_utilBytesCount1_++;
                m_utilCount2_ -= BOTTOM_COUNT_2_;
            }
            m_utilBytes1_ = append(m_utilBytes1_, m_utilBytesCount1_, (byte) (COMMON_BOTTOM_2_ + (m_utilCount2_ - 1)));
            m_utilBytesCount1_++;
        }
    }

    /**
     * Compacts the secondary bytes and stores them into the primary array
     * 
     * @param doFrench
     *            flag indicator that French has to be handled specially
     */
    private final void doSecondary(boolean doFrench) {
        if (m_utilCount2_ > 0) {
            while (m_utilCount2_ > BOTTOM_COUNT_2_) {
                m_utilBytes2_ = append(m_utilBytes2_, m_utilBytesCount2_, (byte) (COMMON_BOTTOM_2_ + BOTTOM_COUNT_2_));
                m_utilBytesCount2_++;
                m_utilCount2_ -= BOTTOM_COUNT_2_;
            }
            m_utilBytes2_ = append(m_utilBytes2_, m_utilBytesCount2_, (byte) (COMMON_BOTTOM_2_ + (m_utilCount2_ - 1)));
            m_utilBytesCount2_++;
        }

        m_utilBytes1_ = append(m_utilBytes1_, m_utilBytesCount1_, SORT_LEVEL_TERMINATOR_);
        m_utilBytesCount1_++;

        if (doFrench) { // do the reverse copy
            doFrench();
        } else {
            if (m_utilBytes1_.length <= m_utilBytesCount1_ + m_utilBytesCount2_) {
                m_utilBytes1_ = increase(m_utilBytes1_, m_utilBytesCount1_, m_utilBytesCount2_);
            }
            System.arraycopy(m_utilBytes2_, 0, m_utilBytes1_, m_utilBytesCount1_, m_utilBytesCount2_);
            m_utilBytesCount1_ += m_utilBytesCount2_;
        }
    }

    /**
     * Increase buffer size
     * 
     * @param buffer
     *            array of bytes
     * @param size
     *            of the byte array
     * @param incrementsize
     *            size to increase
     * @return the new buffer
     */
    private static final byte[] increase(byte buffer[], int size, int incrementsize) {
        byte result[] = new byte[buffer.length + incrementsize];
        System.arraycopy(buffer, 0, result, 0, size);
        return result;
    }

    /**
     * Increase buffer size
     * 
     * @param buffer
     *            array of ints
     * @param size
     *            of the byte array
     * @param incrementsize
     *            size to increase
     * @return the new buffer
     */
    private static final int[] increase(int buffer[], int size, int incrementsize) {
        int result[] = new int[buffer.length + incrementsize];
        System.arraycopy(buffer, 0, result, 0, size);
        return result;
    }

    /**
     * Compacts the case bytes and stores them into the primary array
     */
    private final void doCase() {
        m_utilBytes1_ = append(m_utilBytes1_, m_utilBytesCount1_, SORT_LEVEL_TERMINATOR_);
        m_utilBytesCount1_++;
        if (m_utilBytes1_.length <= m_utilBytesCount1_ + m_utilBytesCount0_) {
            m_utilBytes1_ = increase(m_utilBytes1_, m_utilBytesCount1_, m_utilBytesCount0_);
        }
        System.arraycopy(m_utilBytes0_, 0, m_utilBytes1_, m_utilBytesCount1_, m_utilBytesCount0_);
        m_utilBytesCount1_ += m_utilBytesCount0_;
    }

    /**
     * Compacts the tertiary bytes and stores them into the primary array
     */
    private final void doTertiary() {
        if (m_utilCount3_ > 0) {
            if (m_common3_ != COMMON_BOTTOM_3_) {
                while (m_utilCount3_ >= m_topCount3_) {
                    m_utilBytes3_ = append(m_utilBytes3_, m_utilBytesCount3_, (byte) (m_top3_ - m_topCount3_));
                    m_utilBytesCount3_++;
                    m_utilCount3_ -= m_topCount3_;
                }
                m_utilBytes3_ = append(m_utilBytes3_, m_utilBytesCount3_, (byte) (m_top3_ - m_utilCount3_));
                m_utilBytesCount3_++;
            } else {
                while (m_utilCount3_ > m_bottomCount3_) {
                    m_utilBytes3_ = append(m_utilBytes3_, m_utilBytesCount3_, (byte) (m_bottom3_ + m_bottomCount3_));
                    m_utilBytesCount3_++;
                    m_utilCount3_ -= m_bottomCount3_;
                }
                m_utilBytes3_ = append(m_utilBytes3_, m_utilBytesCount3_, (byte) (m_bottom3_ + (m_utilCount3_ - 1)));
                m_utilBytesCount3_++;
            }
        }
        m_utilBytes1_ = append(m_utilBytes1_, m_utilBytesCount1_, SORT_LEVEL_TERMINATOR_);
        m_utilBytesCount1_++;
        if (m_utilBytes1_.length <= m_utilBytesCount1_ + m_utilBytesCount3_) {
            m_utilBytes1_ = increase(m_utilBytes1_, m_utilBytesCount1_, m_utilBytesCount3_);
        }
        System.arraycopy(m_utilBytes3_, 0, m_utilBytes1_, m_utilBytesCount1_, m_utilBytesCount3_);
        m_utilBytesCount1_ += m_utilBytesCount3_;
    }

    /**
     * Compacts the quaternary bytes and stores them into the primary array
     */
    private final void doQuaternary(int commonbottom4, int bottomcount4) {
        if (m_utilCount4_ > 0) {
            while (m_utilCount4_ > bottomcount4) {
                m_utilBytes4_ = append(m_utilBytes4_, m_utilBytesCount4_, (byte) (commonbottom4 + bottomcount4));
                m_utilBytesCount4_++;
                m_utilCount4_ -= bottomcount4;
            }
            m_utilBytes4_ = append(m_utilBytes4_, m_utilBytesCount4_, (byte) (commonbottom4 + (m_utilCount4_ - 1)));
            m_utilBytesCount4_++;
        }
        m_utilBytes1_ = append(m_utilBytes1_, m_utilBytesCount1_, SORT_LEVEL_TERMINATOR_);
        m_utilBytesCount1_++;
        if (m_utilBytes1_.length <= m_utilBytesCount1_ + m_utilBytesCount4_) {
            m_utilBytes1_ = increase(m_utilBytes1_, m_utilBytesCount1_, m_utilBytesCount4_);
        }
        System.arraycopy(m_utilBytes4_, 0, m_utilBytes1_, m_utilBytesCount1_, m_utilBytesCount4_);
        m_utilBytesCount1_ += m_utilBytesCount4_;
    }

    /**
     * Deals with the identical sort. Appends the BOCSU version of the source string to the ends of the byte buffer.
     * 
     * @param source
     *            text string
     */
    private final void doIdentical(String source) {
        int isize = BOCU.getCompressionLength(source);
        m_utilBytes1_ = append(m_utilBytes1_, m_utilBytesCount1_, SORT_LEVEL_TERMINATOR_);
        m_utilBytesCount1_++;
        if (m_utilBytes1_.length <= m_utilBytesCount1_ + isize) {
            m_utilBytes1_ = increase(m_utilBytes1_, m_utilBytesCount1_, 1 + isize);
        }
        m_utilBytesCount1_ = BOCU.compress(source, m_utilBytes1_, m_utilBytesCount1_);
    }

    /**
     * Gets the offset of the first unmatched characters in source and target. This method returns the offset of the
     * start of a contraction or a combining sequence, if the first difference is in the middle of such a sequence.
     * 
     * @param source
     *            string
     * @param target
     *            string
     * @return offset of the first unmatched characters in source and target.
     */
    private final int getFirstUnmatchedOffset(String source, String target) {
        int result = 0;
        int slength = source.length();
        int tlength = target.length();
        int minlength = slength;
        if (minlength > tlength) {
            minlength = tlength;
        }
        while (result < minlength && source.charAt(result) == target.charAt(result)) {
            result++;
        }
        if (result > 0) {
            // There is an identical portion at the beginning of the two
            // strings. If the identical portion ends within a contraction or a
            // combining character sequence, back up to the start of that
            // sequence.
            char schar = 0;
            char tchar = 0;
            if (result < minlength) {
                schar = source.charAt(result); // first differing chars
                tchar = target.charAt(result);
            } else {
                schar = source.charAt(minlength - 1);
                if (isUnsafe(schar)) {
                    tchar = schar;
                } else if (slength == tlength) {
                    return result;
                } else if (slength < tlength) {
                    tchar = target.charAt(result);
                } else {
                    schar = source.charAt(result);
                }
            }
            if (isUnsafe(schar) || isUnsafe(tchar)) {
                // We are stopped in the middle of a contraction or combining
                // sequence.
                // Look backwards for the part of the string for the start of
                // the sequence
                // It doesn't matter which string we scan, since they are the
                // same in this region.
                do {
                    result--;
                } while (result > 0 && isUnsafe(source.charAt(result)));
            }
        }
        return result;
    }

    /**
     * Appending an byte to an array of bytes and increases it if we run out of space
     * 
     * @param array
     *            of byte arrays
     * @param appendindex
     *            index in the byte array to append
     * @param value
     *            to append
     * @return array if array size can accomodate the new value, otherwise a bigger array will be created and returned
     */
    private static final byte[] append(byte array[], int appendindex, byte value) {
        try {
            array[appendindex] = value;
        } catch (ArrayIndexOutOfBoundsException e) {
            array = increase(array, appendindex, SORT_BUFFER_INIT_SIZE_);
            array[appendindex] = value;
        }
        return array;
    }

    /**
     * This is a trick string compare function that goes in and uses sortkeys to compare. It is used when compare gets
     * in trouble and needs to bail out.
     * 
     * @param source
     *            text string
     * @param target
     *            text string
     */
    private final int compareBySortKeys(String source, String target)

    {
        m_utilRawCollationKey_ = getRawCollationKey(source, m_utilRawCollationKey_);
        // this method is very seldom called
        RawCollationKey targetkey = getRawCollationKey(target, null);
        return m_utilRawCollationKey_.compareTo(targetkey);
    }

    /**
     * Performs the primary comparisons, and fills up the CE buffer at the same time. The return value toggles between
     * the comparison result and the hiragana result. If either the source is greater than target or vice versa, the
     * return result is the comparison result, ie 1 or -1, furthermore the cebuffers will be cleared when that happens.
     * If the primary comparisons are equal, we'll have to continue with secondary comparison. In this case the cebuffer
     * will not be cleared and the return result will be the hiragana result.
     * 
     * @param doHiragana4
     *            flag indicator that Hiragana Quaternary has to be observed
     * @param lowestpvalue
     *            the lowest primary value that will not be ignored if alternate handling is shifted
     * @param source
     *            text string
     * @param target
     *            text string
     * @param textoffset
     *            offset in text to start the comparison
     * @return comparion result if a primary difference is found, otherwise hiragana result
     */
    private final int doPrimaryCompare(boolean doHiragana4, int lowestpvalue, String source, String target,
            int textoffset)

    {
        // Preparing the context objects for iterating over strings
        m_srcUtilIter_.setText(source);
        m_srcUtilColEIter_.setText(m_srcUtilIter_, textoffset);
        m_tgtUtilIter_.setText(target);
        m_tgtUtilColEIter_.setText(m_tgtUtilIter_, textoffset);

        // Non shifted primary processing is quite simple
        if (!m_isAlternateHandlingShifted_) {
            int hiraganaresult = 0;
            while (true) {
                int sorder = 0;
                // We fetch CEs until we hit a non ignorable primary or end.
                do {
                    sorder = m_srcUtilColEIter_.next();
                    m_srcUtilCEBuffer_ = append(m_srcUtilCEBuffer_, m_srcUtilCEBufferSize_, sorder);
                    m_srcUtilCEBufferSize_++;
                    sorder &= CE_PRIMARY_MASK_;
                } while (sorder == CollationElementIterator.IGNORABLE);

                int torder = 0;
                do {
                    torder = m_tgtUtilColEIter_.next();
                    m_tgtUtilCEBuffer_ = append(m_tgtUtilCEBuffer_, m_tgtUtilCEBufferSize_, torder);
                    m_tgtUtilCEBufferSize_++;
                    torder &= CE_PRIMARY_MASK_;
                } while (torder == CollationElementIterator.IGNORABLE);

                if (!isContinuation(sorder) && m_leadBytePermutationTable_ != null) {
                    sorder = (m_leadBytePermutationTable_[((sorder >> 24) + 256) % 256] << 24) | (sorder & 0x00FFFFFF);
                    torder = (m_leadBytePermutationTable_[((torder >> 24) + 256) % 256] << 24) | (torder & 0x00FFFFFF);
                }

                // if both primaries are the same
                if (sorder == torder) {
                    // and there are no more CEs, we advance to the next level
                    // see if we are at the end of either string
                    if (m_srcUtilCEBuffer_[m_srcUtilCEBufferSize_ - 1] == CollationElementIterator.NULLORDER) {
                        if (m_tgtUtilCEBuffer_[m_tgtUtilCEBufferSize_ - 1] != CollationElementIterator.NULLORDER) {
                            return -1;
                        }
                        break;
                    } else if (m_tgtUtilCEBuffer_[m_tgtUtilCEBufferSize_ - 1] == CollationElementIterator.NULLORDER) {
                        return 1;
                    }
                    if (doHiragana4 && hiraganaresult == 0
                            && m_srcUtilColEIter_.m_isCodePointHiragana_ != m_tgtUtilColEIter_.m_isCodePointHiragana_) {
                        if (m_srcUtilColEIter_.m_isCodePointHiragana_) {
                            hiraganaresult = -1;
                        } else {
                            hiraganaresult = 1;
                        }
                    }
                } else {
                    // if two primaries are different, we are done
                    return endPrimaryCompare(sorder, torder);
                }
            }
            // no primary difference... do the rest from the buffers
            return hiraganaresult;
        } else { // shifted - do a slightly more complicated processing :)
            while (true) {
                int sorder = getPrimaryShiftedCompareCE(m_srcUtilColEIter_, lowestpvalue, true);
                int torder = getPrimaryShiftedCompareCE(m_tgtUtilColEIter_, lowestpvalue, false);
                if (sorder == torder) {
                    if (m_srcUtilCEBuffer_[m_srcUtilCEBufferSize_ - 1] == CollationElementIterator.NULLORDER) {
                        break;
                    } else {
                        continue;
                    }
                } else {
                    return endPrimaryCompare(sorder, torder);
                }
            } // no primary difference... do the rest from the buffers
        }
        return 0;
    }

    /**
     * This is used only for primary strength when we know that sorder is already different from torder. Compares sorder
     * and torder, returns -1 if sorder is less than torder. Clears the cebuffer at the same time.
     * 
     * @param sorder
     *            source strength order
     * @param torder
     *            target strength order
     * @return the comparison result of sorder and torder
     */
    private final int endPrimaryCompare(int sorder, int torder) {
        // if we reach here, the ce offset accessed is the last ce
        // appended to the buffer
        boolean isSourceNullOrder = (m_srcUtilCEBuffer_[m_srcUtilCEBufferSize_ - 1] == CollationElementIterator.NULLORDER);
        boolean isTargetNullOrder = (m_tgtUtilCEBuffer_[m_tgtUtilCEBufferSize_ - 1] == CollationElementIterator.NULLORDER);
        m_srcUtilCEBufferSize_ = -1;
        m_tgtUtilCEBufferSize_ = -1;
        if (isSourceNullOrder) {
            return -1;
        }
        if (isTargetNullOrder) {
            return 1;
        }
        // getting rid of the sign
        sorder >>>= CE_PRIMARY_SHIFT_;
                    torder >>>= CE_PRIMARY_SHIFT_;
                    if (sorder < torder) {
                        return -1;
                    }
                    return 1;
    }

    /**
     * Calculates the next primary shifted value and fills up cebuffer with the next non-ignorable ce.
     * 
     * @param coleiter
     *            collation element iterator
     * @param doHiragana4
     *            flag indicator if hiragana quaternary is to be handled
     * @param lowestpvalue
     *            lowest primary shifted value that will not be ignored
     * @return result next modified ce
     */
    private final int getPrimaryShiftedCompareCE(CollationElementIterator coleiter, int lowestpvalue, boolean isSrc)

    {
        boolean shifted = false;
        int result = CollationElementIterator.IGNORABLE;
        int cebuffer[] = m_srcUtilCEBuffer_;
        int cebuffersize = m_srcUtilCEBufferSize_;
        if (!isSrc) {
            cebuffer = m_tgtUtilCEBuffer_;
            cebuffersize = m_tgtUtilCEBufferSize_;
        }
        while (true) {
            result = coleiter.next();
            if (result == CollationElementIterator.NULLORDER) {
                cebuffer = append(cebuffer, cebuffersize, result);
                cebuffersize++;
                break;
            } else if (result == CollationElementIterator.IGNORABLE
                    || (shifted && (result & CE_PRIMARY_MASK_) == CollationElementIterator.IGNORABLE)) {
                // UCA amendment - ignore ignorables that follow shifted code
                // points
                continue;
            } else if (isContinuation(result)) {
                if ((result & CE_PRIMARY_MASK_) != CollationElementIterator.IGNORABLE) {
                    // There is primary value
                    if (shifted) {
                        result = (result & CE_PRIMARY_MASK_) | CE_CONTINUATION_MARKER_;
                        // preserve interesting continuation
                        cebuffer = append(cebuffer, cebuffersize, result);
                        cebuffersize++;
                        continue;
                    } else {
                        cebuffer = append(cebuffer, cebuffersize, result);
                        cebuffersize++;
                        break;
                    }
                } else { // Just lower level values
                    if (!shifted) {
                        cebuffer = append(cebuffer, cebuffersize, result);
                        cebuffersize++;
                    }
                }
            } else { // regular
                if (Utility.compareUnsigned(result & CE_PRIMARY_MASK_, lowestpvalue) > 0) {
                    cebuffer = append(cebuffer, cebuffersize, result);
                    cebuffersize++;
                    break;
                } else {
                    if ((result & CE_PRIMARY_MASK_) != 0) {
                        shifted = true;
                        result &= CE_PRIMARY_MASK_;
                        cebuffer = append(cebuffer, cebuffersize, result);
                        cebuffersize++;
                        continue;
                    } else {
                        cebuffer = append(cebuffer, cebuffersize, result);
                        cebuffersize++;
                        shifted = false;
                        continue;
                    }
                }
            }
        }
        if (isSrc) {
            m_srcUtilCEBuffer_ = cebuffer;
            m_srcUtilCEBufferSize_ = cebuffersize;
        } else {
            m_tgtUtilCEBuffer_ = cebuffer;
            m_tgtUtilCEBufferSize_ = cebuffersize;
        }
        result &= CE_PRIMARY_MASK_;
        return result;
    }

    /**
     * Appending an int to an array of ints and increases it if we run out of space
     * 
     * @param array
     *            of int arrays
     * @param appendindex
     *            index at which value will be appended
     * @param value
     *            to append
     * @return array if size is not increased, otherwise a new array will be returned
     */
    private static final int[] append(int array[], int appendindex, int value) {
        if (appendindex + 1 >= array.length) {
            array = increase(array, appendindex, CE_BUFFER_SIZE_);
        }
        array[appendindex] = value;
        return array;
    }

    /**
     * Does secondary strength comparison based on the collected ces.
     * 
     * @param doFrench
     *            flag indicates if French ordering is to be done
     * @return the secondary strength comparison result
     */
    private final int doSecondaryCompare(boolean doFrench) {
        // now, we're gonna reexamine collected CEs
        if (!doFrench) { // normal
            int soffset = 0;
            int toffset = 0;
            while (true) {
                int sorder = CollationElementIterator.IGNORABLE;
                while (sorder == CollationElementIterator.IGNORABLE) {
                    sorder = m_srcUtilCEBuffer_[soffset++] & CE_SECONDARY_MASK_;
                }
                int torder = CollationElementIterator.IGNORABLE;
                while (torder == CollationElementIterator.IGNORABLE) {
                    torder = m_tgtUtilCEBuffer_[toffset++] & CE_SECONDARY_MASK_;
                }

                if (sorder == torder) {
                    if (m_srcUtilCEBuffer_[soffset - 1] == CollationElementIterator.NULLORDER) {
                        if (m_tgtUtilCEBuffer_[toffset - 1] != CollationElementIterator.NULLORDER) {
                            return -1;
                        }
                        break;
                    } else if (m_tgtUtilCEBuffer_[toffset - 1] == CollationElementIterator.NULLORDER) {
                        return 1;
                    }
                } else {
                    if (m_srcUtilCEBuffer_[soffset - 1] == CollationElementIterator.NULLORDER) {
                        return -1;
                    }
                    if (m_tgtUtilCEBuffer_[toffset - 1] == CollationElementIterator.NULLORDER) {
                        return 1;
                    }
                    return (sorder < torder) ? -1 : 1;
                }
            }
        } else { // do the French
            m_srcUtilContOffset_ = 0;
            m_tgtUtilContOffset_ = 0;
            m_srcUtilOffset_ = m_srcUtilCEBufferSize_ - 2;
            m_tgtUtilOffset_ = m_tgtUtilCEBufferSize_ - 2;
            while (true) {
                int sorder = getSecondaryFrenchCE(true);
                int torder = getSecondaryFrenchCE(false);
                if (sorder == torder) {
                    if ((m_srcUtilOffset_ < 0 && m_tgtUtilOffset_ < 0)
                            || (m_srcUtilOffset_ >= 0 && m_srcUtilCEBuffer_[m_srcUtilOffset_] == CollationElementIterator.NULLORDER)) {
                        break;
                    }
                } else {
                    return (sorder < torder) ? -1 : 1;
                }
            }
        }
        return 0;
    }

    /**
     * Calculates the next secondary french CE.
     * 
     * @param isSrc
     *            flag indicator if we are calculating the src ces
     * @return result next modified ce
     */
    private final int getSecondaryFrenchCE(boolean isSrc) {
        int result = CollationElementIterator.IGNORABLE;
        int offset = m_srcUtilOffset_;
        int continuationoffset = m_srcUtilContOffset_;
        int cebuffer[] = m_srcUtilCEBuffer_;
        if (!isSrc) {
            offset = m_tgtUtilOffset_;
            continuationoffset = m_tgtUtilContOffset_;
            cebuffer = m_tgtUtilCEBuffer_;
        }

        while (result == CollationElementIterator.IGNORABLE && offset >= 0) {
            if (continuationoffset == 0) {
                result = cebuffer[offset];
                while (isContinuation(cebuffer[offset--])) {
                }
                // after this, sorder is at the start of continuation,
                // and offset points before that
                if (isContinuation(cebuffer[offset + 1])) {
                    // save offset for later
                    continuationoffset = offset;
                    offset += 2;
                }
            } else {
                result = cebuffer[offset++];
                if (!isContinuation(result)) {
                    // we have finished with this continuation
                    offset = continuationoffset;
                    // reset the pointer to before continuation
                    continuationoffset = 0;
                    continue;
                }
            }
            result &= CE_SECONDARY_MASK_; // remove continuation bit
        }
        if (isSrc) {
            m_srcUtilOffset_ = offset;
            m_srcUtilContOffset_ = continuationoffset;
        } else {
            m_tgtUtilOffset_ = offset;
            m_tgtUtilContOffset_ = continuationoffset;
        }
        return result;
    }

    /**
     * Does case strength comparison based on the collected ces.
     * 
     * @return the case strength comparison result
     */
    private final int doCaseCompare() {
        int soffset = 0;
        int toffset = 0;
        while (true) {
            int sorder = CollationElementIterator.IGNORABLE;
            int torder = CollationElementIterator.IGNORABLE;
            while ((sorder & CE_REMOVE_CASE_) == CollationElementIterator.IGNORABLE) {
                sorder = m_srcUtilCEBuffer_[soffset++];
                if (!isContinuation(sorder) && ((sorder & CE_PRIMARY_MASK_) != 0 || m_utilCompare2_ == true)) {
                    // primary ignorables should not be considered on the case level when the strength is primary
                    // otherwise, the CEs stop being well-formed
                    sorder &= CE_CASE_MASK_3_;
                    sorder ^= m_caseSwitch_;
                } else {
                    sorder = CollationElementIterator.IGNORABLE;
                }
            }

            while ((torder & CE_REMOVE_CASE_) == CollationElementIterator.IGNORABLE) {
                torder = m_tgtUtilCEBuffer_[toffset++];
                if (!isContinuation(torder) && ((torder & CE_PRIMARY_MASK_) != 0 || m_utilCompare2_ == true)) {
                    // primary ignorables should not be considered on the case level when the strength is primary
                    // otherwise, the CEs stop being well-formed
                    torder &= CE_CASE_MASK_3_;
                    torder ^= m_caseSwitch_;
                } else {
                    torder = CollationElementIterator.IGNORABLE;
                }
            }

            sorder &= CE_CASE_BIT_MASK_;
            torder &= CE_CASE_BIT_MASK_;
            if (sorder == torder) {
                // checking end of strings
                if (m_srcUtilCEBuffer_[soffset - 1] == CollationElementIterator.NULLORDER) {
                    if (m_tgtUtilCEBuffer_[toffset - 1] != CollationElementIterator.NULLORDER) {
                        return -1;
                    }
                    break;
                } else if (m_tgtUtilCEBuffer_[toffset - 1] == CollationElementIterator.NULLORDER) {
                    return 1;
                }
            } else {
                if (m_srcUtilCEBuffer_[soffset - 1] == CollationElementIterator.NULLORDER) {
                    return -1;
                }
                if (m_tgtUtilCEBuffer_[soffset - 1] == CollationElementIterator.NULLORDER) {
                    return 1;
                }
                return (sorder < torder) ? -1 : 1;
            }
        }
        return 0;
    }

    /**
     * Does tertiary strength comparison based on the collected ces.
     * 
     * @return the tertiary strength comparison result
     */
    private final int doTertiaryCompare() {
        int soffset = 0;
        int toffset = 0;
        while (true) {
            int sorder = CollationElementIterator.IGNORABLE;
            int torder = CollationElementIterator.IGNORABLE;
            while ((sorder & CE_REMOVE_CASE_) == CollationElementIterator.IGNORABLE) {
                sorder = m_srcUtilCEBuffer_[soffset++] & m_mask3_;
                if (!isContinuation(sorder)) {
                    sorder ^= m_caseSwitch_;
                } else {
                    sorder &= CE_REMOVE_CASE_;
                }
            }

            while ((torder & CE_REMOVE_CASE_) == CollationElementIterator.IGNORABLE) {
                torder = m_tgtUtilCEBuffer_[toffset++] & m_mask3_;
                if (!isContinuation(torder)) {
                    torder ^= m_caseSwitch_;
                } else {
                    torder &= CE_REMOVE_CASE_;
                }
            }

            if (sorder == torder) {
                if (m_srcUtilCEBuffer_[soffset - 1] == CollationElementIterator.NULLORDER) {
                    if (m_tgtUtilCEBuffer_[toffset - 1] != CollationElementIterator.NULLORDER) {
                        return -1;
                    }
                    break;
                } else if (m_tgtUtilCEBuffer_[toffset - 1] == CollationElementIterator.NULLORDER) {
                    return 1;
                }
            } else {
                if (m_srcUtilCEBuffer_[soffset - 1] == CollationElementIterator.NULLORDER) {
                    return -1;
                }
                if (m_tgtUtilCEBuffer_[toffset - 1] == CollationElementIterator.NULLORDER) {
                    return 1;
                }
                return (sorder < torder) ? -1 : 1;
            }
        }
        return 0;
    }

    /**
     * Does quaternary strength comparison based on the collected ces.
     * 
     * @param lowestpvalue
     *            the lowest primary value that will not be ignored if alternate handling is shifted
     * @return the quaternary strength comparison result
     */
    private final int doQuaternaryCompare(int lowestpvalue) {
        boolean sShifted = true;
        boolean tShifted = true;
        int soffset = 0;
        int toffset = 0;
        while (true) {
            int sorder = CollationElementIterator.IGNORABLE;
            int torder = CollationElementIterator.IGNORABLE;
            while (sorder == CollationElementIterator.IGNORABLE || (isContinuation(sorder) && !sShifted)) {
                sorder = m_srcUtilCEBuffer_[soffset++];
                if (isContinuation(sorder)) {
                    if (!sShifted) {
                        continue;
                    }
                } else if (Utility.compareUnsigned(sorder, lowestpvalue) > 0
                        || (sorder & CE_PRIMARY_MASK_) == CollationElementIterator.IGNORABLE) {
                    // non continuation
                    sorder = CE_PRIMARY_MASK_;
                    sShifted = false;
                } else {
                    sShifted = true;
                }
            }
            sorder >>>= CE_PRIMARY_SHIFT_;
                    while (torder == CollationElementIterator.IGNORABLE || (isContinuation(torder) && !tShifted)) {
                        torder = m_tgtUtilCEBuffer_[toffset++];
                        if (isContinuation(torder)) {
                            if (!tShifted) {
                                continue;
                            }
                        } else if (Utility.compareUnsigned(torder, lowestpvalue) > 0
                                || (torder & CE_PRIMARY_MASK_) == CollationElementIterator.IGNORABLE) {
                            // non continuation
                            torder = CE_PRIMARY_MASK_;
                            tShifted = false;
                        } else {
                            tShifted = true;
                        }
                    }
                    torder >>>= CE_PRIMARY_SHIFT_;

                    if (sorder == torder) {
                        if (m_srcUtilCEBuffer_[soffset - 1] == CollationElementIterator.NULLORDER) {
                            if (m_tgtUtilCEBuffer_[toffset - 1] != CollationElementIterator.NULLORDER) {
                                return -1;
                            }
                            break;
                        } else if (m_tgtUtilCEBuffer_[toffset - 1] == CollationElementIterator.NULLORDER) {
                            return 1;
                        }
                    } else {
                        if (m_srcUtilCEBuffer_[soffset - 1] == CollationElementIterator.NULLORDER) {
                            return -1;
                        }
                        if (m_tgtUtilCEBuffer_[toffset - 1] == CollationElementIterator.NULLORDER) {
                            return 1;
                        }
                        return (sorder < torder) ? -1 : 1;
                    }
        }
        return 0;
    }

    /**
     * Internal function. Does byte level string compare. Used by strcoll if strength == identical and strings are
     * otherwise equal. This is a rare case. Comparison must be done on NFD normalized strings. FCD is not good enough.
     * 
     * @param source
     *            text
     * @param target
     *            text
     * @param offset
     *            of the first difference in the text strings
     * @param normalize
     *            flag indicating if we are to normalize the text before comparison
     * @return 1 if source is greater than target, -1 less than and 0 if equals
     */
    private static final int doIdenticalCompare(String source, String target, int offset, boolean normalize)

    {
        if (normalize) {
            if (Normalizer.quickCheck(source, Normalizer.NFD, 0) != Normalizer.YES) {
                source = Normalizer.decompose(source, false);
            }

            if (Normalizer.quickCheck(target, Normalizer.NFD, 0) != Normalizer.YES) {
                target = Normalizer.decompose(target, false);
            }
            offset = 0;
        }

        return doStringCompare(source, target, offset);
    }

    /**
     * Compares string for their codepoint order. This comparison handles surrogate characters and place them after the
     * all non surrogate characters.
     * 
     * @param source
     *            text
     * @param target
     *            text
     * @param offset
     *            start offset for comparison
     * @return 1 if source is greater than target, -1 less than and 0 if equals
     */
    private static final int doStringCompare(String source, String target, int offset) {
        // compare identical prefixes - they do not need to be fixed up
        char schar = 0;
        char tchar = 0;
        int slength = source.length();
        int tlength = target.length();
        int minlength = Math.min(slength, tlength);
        while (offset < minlength) {
            schar = source.charAt(offset);
            tchar = target.charAt(offset++);
            if (schar != tchar) {
                break;
            }
        }

        if (schar == tchar && offset == minlength) {
            if (slength > minlength) {
                return 1;
            }
            if (tlength > minlength) {
                return -1;
            }
            return 0;
        }

        // if both values are in or above the surrogate range, Fix them up.
        if (schar >= UTF16.LEAD_SURROGATE_MIN_VALUE && tchar >= UTF16.LEAD_SURROGATE_MIN_VALUE) {
            schar = fixupUTF16(schar);
            tchar = fixupUTF16(tchar);
        }

        // now c1 and c2 are in UTF-32-compatible order
        return (schar < tchar) ? -1 : 1; // schar and tchar has to be different
    }

    /**
     * Rotate surrogates to the top to get code point order
     */
    private static final char fixupUTF16(char ch) {
        if (ch >= 0xe000) {
            ch -= 0x800;
        } else {
            ch += 0x2000;
        }
        return ch;
    }

    private static final int UCOL_REORDER_CODE_IGNORE = ReorderCodes.LIMIT + 1;
    /**
     * Builds the lead byte permuatation table
     */
    private void buildPermutationTable() {
        if (m_reorderCodes_ == null) {
            m_leadBytePermutationTable_ = null;
            return;
        }

        // TODO - these need to be read in from the UCA data file
        // The lowest byte that hasn't been assigned a mapping
        int toBottom = 0x03;
        // The highest byte that hasn't been assigned a mapping
        int toTop = 0xe4;

        // filled slots in the output m_scriptOrder_
        boolean[] permutationSlotFilled = new boolean[256];

        // used lead bytes
        boolean[] newLeadByteUsed = new boolean[256];

        if (m_leadBytePermutationTable_ == null) {
            m_leadBytePermutationTable_ = new byte[256];
        }

        // prefill the reordering codes with the leading entries
        int[] internalReorderCodes = new int[m_reorderCodes_.length + (ReorderCodes.LIMIT - ReorderCodes.FIRST)];
        for (int codeIndex = 0; codeIndex < ReorderCodes.LIMIT - ReorderCodes.FIRST; codeIndex++) {
            internalReorderCodes[codeIndex] = ReorderCodes.FIRST + codeIndex;
        }
        for (int codeIndex = 0; codeIndex < m_reorderCodes_.length; codeIndex++) {
            internalReorderCodes[codeIndex + (ReorderCodes.LIMIT - ReorderCodes.FIRST)] = m_reorderCodes_[codeIndex];
            if (m_reorderCodes_[codeIndex] >= ReorderCodes.FIRST && m_reorderCodes_[codeIndex] < ReorderCodes.LIMIT) {
                internalReorderCodes[m_reorderCodes_[codeIndex] - ReorderCodes.FIRST] = UCOL_REORDER_CODE_IGNORE;
            }
        }

        /*
         * Start from the front of the list and place each script we encounter at the earliest possible locatation
         * in the permutation table. If we encounter UNKNOWN, start processing from the back, and place each script
         * in the last possible location. At each step, we also need to make sure that any scripts that need to not
         * be moved are copied to their same location in the final table.
         */
        boolean fromTheBottom = true;
        for (int reorderCodesIndex = 0; reorderCodesIndex < internalReorderCodes.length; reorderCodesIndex++) {
            int next = internalReorderCodes[reorderCodesIndex];
            if (next == UCOL_REORDER_CODE_IGNORE) {
                continue;
            }
            if (next == UScript.UNKNOWN) {
                if (fromTheBottom == false) {
                    // double turnaround
                    m_leadBytePermutationTable_ = null;
                    throw new IllegalArgumentException("Illegal collation reorder codes - two \"from the end\" markers.");
                }
                fromTheBottom = false;
                continue;
            }

            int[] leadBytes = RuleBasedCollator.LEADBYTE_CONSTANTS_.getLeadBytesForReorderCode(next);
            if (fromTheBottom) {
                for (int leadByte : leadBytes) {
                    // don't place a lead byte twice in the permutation table
                    if (permutationSlotFilled[leadByte]) {
                        // lead byte already used
                        m_leadBytePermutationTable_ = null;
                        throw new IllegalArgumentException("Illegal reorder codes specified - multiple codes with the same lead byte.");
                    }
                    m_leadBytePermutationTable_[leadByte] = (byte) toBottom;
                    newLeadByteUsed[toBottom] = true;
                    permutationSlotFilled[leadByte] = true;
                    toBottom++;                    
                }
            } else {
                for (int leadByteIndex = leadBytes.length - 1; leadByteIndex >= 0; leadByteIndex--) {
                    int leadByte = leadBytes[leadByteIndex];
                    // don't place a lead byte twice in the permutation table
                    if (permutationSlotFilled[leadByte]) {
                        // lead byte already used
                        m_leadBytePermutationTable_ = null;
                        throw new IllegalArgumentException("Illegal reorder codes specified - multiple codes with the same lead byte.");
                    }

                    m_leadBytePermutationTable_[leadByte] = (byte) toTop;
                    newLeadByteUsed[toTop] = true;
                    permutationSlotFilled[leadByte] = true;
                    toTop--;                    
                }
            }
        }

        /* Copy everything that's left over */
        int reorderCode = 0;
        for (int i = 0; i < 256; i++) {
            if (!permutationSlotFilled[i]) {
                while (newLeadByteUsed[reorderCode]) {
                    if (reorderCode > 255) {
                        throw new IllegalArgumentException("Unable to fill collation reordering table slots - no available reordering code.");
                    }
                    reorderCode++;
                }
                m_leadBytePermutationTable_[i] = (byte) reorderCode;
                permutationSlotFilled[i] = true;
                newLeadByteUsed[reorderCode] = true;
            }
        } 

        // for (int i = 0; i < 256; i++){
        // System.out.println(Integer.toString(i, 16) + " -> " + Integer.toString(m_scriptReorderTable_[i], 16));
        // }
        latinOneRegenTable_ = true;
        updateInternalState();
    }

    /**
     * Resets the internal case data members and compression values.
     */
    private void updateInternalState() {
        if (m_caseFirst_ == AttributeValue.UPPER_FIRST_) {
            m_caseSwitch_ = CASE_SWITCH_;
        } else {
            m_caseSwitch_ = NO_CASE_SWITCH_;
        }

        if (m_isCaseLevel_ || m_caseFirst_ == AttributeValue.OFF_) {
            m_mask3_ = CE_REMOVE_CASE_;
            m_common3_ = COMMON_NORMAL_3_;
            m_addition3_ = FLAG_BIT_MASK_CASE_SWITCH_OFF_;
            m_top3_ = COMMON_TOP_CASE_SWITCH_OFF_3_;
            m_bottom3_ = COMMON_BOTTOM_3_;
        } else {
            m_mask3_ = CE_KEEP_CASE_;
            m_addition3_ = FLAG_BIT_MASK_CASE_SWITCH_ON_;
            if (m_caseFirst_ == AttributeValue.UPPER_FIRST_) {
                m_common3_ = COMMON_UPPER_FIRST_3_;
                m_top3_ = COMMON_TOP_CASE_SWITCH_UPPER_3_;
                m_bottom3_ = COMMON_BOTTOM_CASE_SWITCH_UPPER_3_;
            } else {
                m_common3_ = COMMON_NORMAL_3_;
                m_top3_ = COMMON_TOP_CASE_SWITCH_LOWER_3_;
                m_bottom3_ = COMMON_BOTTOM_CASE_SWITCH_LOWER_3_;
            }
        }

        // Set the compression values
        int total3 = m_top3_ - COMMON_BOTTOM_3_ - 1;
        // we multilply double with int, but need only int
        m_topCount3_ = (int) (PROPORTION_3_ * total3);
        m_bottomCount3_ = total3 - m_topCount3_;

        if (!m_isCaseLevel_ && getStrength() == AttributeValue.TERTIARY_ && !m_isFrenchCollation_
                && !m_isAlternateHandlingShifted_) {
            m_isSimple3_ = true;
        } else {
            m_isSimple3_ = false;
        }
        if (!m_isCaseLevel_ && getStrength() <= AttributeValue.TERTIARY_ && !m_isNumericCollation_
                && !m_isAlternateHandlingShifted_ && !latinOneFailed_) {
            if (latinOneCEs_ == null || latinOneRegenTable_) {
                if (setUpLatinOne()) { // if we succeed in building latin1 table, we'll use it
                    latinOneUse_ = true;
                } else {
                    latinOneUse_ = false;
                    latinOneFailed_ = true;
                }
                latinOneRegenTable_ = false;
            } else { // latin1Table exists and it doesn't need to be regenerated, just use it
                latinOneUse_ = true;
            }
        } else {
            latinOneUse_ = false;
        }

    }

    /**
     * Initializes the RuleBasedCollator
     */
    private final void init() {
        for (m_minUnsafe_ = 0; m_minUnsafe_ < DEFAULT_MIN_HEURISTIC_; m_minUnsafe_++) {
            // Find the smallest unsafe char.
            if (isUnsafe(m_minUnsafe_)) {
                break;
            }
        }

        for (m_minContractionEnd_ = 0; m_minContractionEnd_ < DEFAULT_MIN_HEURISTIC_; m_minContractionEnd_++) {
            // Find the smallest contraction-ending char.
            if (isContractionEnd(m_minContractionEnd_)) {
                break;
            }
        }
        latinOneFailed_ = true;
        setStrength(m_defaultStrength_);
        setDecomposition(m_defaultDecomposition_);
        m_variableTopValue_ = m_defaultVariableTopValue_;
        m_isFrenchCollation_ = m_defaultIsFrenchCollation_;
        m_isAlternateHandlingShifted_ = m_defaultIsAlternateHandlingShifted_;
        m_isCaseLevel_ = m_defaultIsCaseLevel_;
        m_caseFirst_ = m_defaultCaseFirst_;
        m_isHiragana4_ = m_defaultIsHiragana4_;
        m_isNumericCollation_ = m_defaultIsNumericCollation_;
        latinOneFailed_ = false;
        if (m_defaultReorderCodes_ != null) {
            m_reorderCodes_ = m_defaultReorderCodes_.clone();
        } else {
            m_reorderCodes_ = null;
        }
        updateInternalState();
    }

    /**
     * Initializes utility iterators and byte buffer used by compare
     */
    private final void initUtility(boolean allocate) {
        if (allocate) {
            if (m_srcUtilIter_ == null) {
                m_srcUtilIter_ = new StringUCharacterIterator();
                m_srcUtilColEIter_ = new CollationElementIterator(m_srcUtilIter_, this);
                m_tgtUtilIter_ = new StringUCharacterIterator();
                m_tgtUtilColEIter_ = new CollationElementIterator(m_tgtUtilIter_, this);
                m_utilBytes0_ = new byte[SORT_BUFFER_INIT_SIZE_CASE_]; // case
                m_utilBytes1_ = new byte[SORT_BUFFER_INIT_SIZE_1_]; // primary
                m_utilBytes2_ = new byte[SORT_BUFFER_INIT_SIZE_2_]; // secondary
                m_utilBytes3_ = new byte[SORT_BUFFER_INIT_SIZE_3_]; // tertiary
                m_utilBytes4_ = new byte[SORT_BUFFER_INIT_SIZE_4_]; // Quaternary
                m_srcUtilCEBuffer_ = new int[CE_BUFFER_SIZE_];
                m_tgtUtilCEBuffer_ = new int[CE_BUFFER_SIZE_];
            }
        } else {
            m_srcUtilIter_ = null;
            m_srcUtilColEIter_ = null;
            m_tgtUtilIter_ = null;
            m_tgtUtilColEIter_ = null;
            m_utilBytes0_ = null;
            m_utilBytes1_ = null;
            m_utilBytes2_ = null;
            m_utilBytes3_ = null;
            m_utilBytes4_ = null;
            m_srcUtilCEBuffer_ = null;
            m_tgtUtilCEBuffer_ = null;
        }
    }

    // Consts for Latin-1 special processing
    private static final int ENDOFLATINONERANGE_ = 0xFF;
    private static final int LATINONETABLELEN_ = (ENDOFLATINONERANGE_ + 50);
    private static final int BAIL_OUT_CE_ = 0xFF000000;

    /**
     * Generate latin-1 tables
     */

    private class shiftValues {
        int primShift = 24;
        int secShift = 24;
        int terShift = 24;
    }

    private final void addLatinOneEntry(char ch, int CE, shiftValues sh) {
        int primary1 = 0, primary2 = 0, secondary = 0, tertiary = 0;
        boolean continuation = isContinuation(CE);
        boolean reverseSecondary = false;
        if (!continuation) {
            tertiary = ((CE & m_mask3_));
            tertiary ^= m_caseSwitch_;
            reverseSecondary = true;
        } else {
            tertiary = (byte) ((CE & CE_REMOVE_CONTINUATION_MASK_));
            tertiary &= CE_REMOVE_CASE_;
            reverseSecondary = false;
        }

        secondary = ((CE >>>= 8) & LAST_BYTE_MASK_);
        primary2 = ((CE >>>= 8) & LAST_BYTE_MASK_);
        primary1 = (CE >>> 8);

        if (primary1 != 0) {
            if (m_leadBytePermutationTable_ != null && !continuation) {
                primary1 = m_leadBytePermutationTable_[primary1];
            }
            latinOneCEs_[ch] |= (primary1 << sh.primShift);
            sh.primShift -= 8;
        }
        if (primary2 != 0) {
            if (sh.primShift < 0) {
                latinOneCEs_[ch] = BAIL_OUT_CE_;
                latinOneCEs_[latinOneTableLen_ + ch] = BAIL_OUT_CE_;
                latinOneCEs_[2 * latinOneTableLen_ + ch] = BAIL_OUT_CE_;
                return;
            }
            latinOneCEs_[ch] |= (primary2 << sh.primShift);
            sh.primShift -= 8;
        }
        if (secondary != 0) {
            if (reverseSecondary && m_isFrenchCollation_) { // reverse secondary
                latinOneCEs_[latinOneTableLen_ + ch] >>>= 8; // make space for secondary
            latinOneCEs_[latinOneTableLen_ + ch] |= (secondary << 24);
            } else { // normal case
                latinOneCEs_[latinOneTableLen_ + ch] |= (secondary << sh.secShift);
            }
            sh.secShift -= 8;
        }
        if (tertiary != 0) {
            latinOneCEs_[2 * latinOneTableLen_ + ch] |= (tertiary << sh.terShift);
            sh.terShift -= 8;
        }
    }

    private final void resizeLatinOneTable(int newSize) {
        int newTable[] = new int[3 * newSize];
        int sizeToCopy = ((newSize < latinOneTableLen_) ? newSize : latinOneTableLen_);
        // uprv_memset(newTable, 0, newSize*sizeof(uint32_t)*3); // automatically cleared.
        System.arraycopy(latinOneCEs_, 0, newTable, 0, sizeToCopy);
        System.arraycopy(latinOneCEs_, latinOneTableLen_, newTable, newSize, sizeToCopy);
        System.arraycopy(latinOneCEs_, 2 * latinOneTableLen_, newTable, 2 * newSize, sizeToCopy);
        latinOneTableLen_ = newSize;
        latinOneCEs_ = newTable;
    }

    private final boolean setUpLatinOne() {
        if (latinOneCEs_ == null || m_reallocLatinOneCEs_) {
            latinOneCEs_ = new int[3 * LATINONETABLELEN_];
            latinOneTableLen_ = LATINONETABLELEN_;
            m_reallocLatinOneCEs_ = false;
        } else {
            Arrays.fill(latinOneCEs_, 0);
        }
        if (m_ContInfo_ == null) {
            m_ContInfo_ = new ContractionInfo();
        }
        char ch = 0;
        // StringBuffer sCh = new StringBuffer();
        // CollationElementIterator it = getCollationElementIterator(sCh.toString());
        CollationElementIterator it = getCollationElementIterator("");

        shiftValues s = new shiftValues();
        int CE = 0;
        char contractionOffset = ENDOFLATINONERANGE_ + 1;

        for (ch = 0; ch <= ENDOFLATINONERANGE_; ch++) {
            s.primShift = 24;
            s.secShift = 24;
            s.terShift = 24;
            if (ch < 0x100) {
                CE = m_trie_.getLatin1LinearValue(ch);
            } else {
                CE = m_trie_.getLeadValue(ch);
                if (CE == CollationElementIterator.CE_NOT_FOUND_) {
                    CE = UCA_.m_trie_.getLeadValue(ch);
                }
            }
            if (!isSpecial(CE)) {
                addLatinOneEntry(ch, CE, s);
            } else {
                switch (RuleBasedCollator.getTag(CE)) {
                case CollationElementIterator.CE_EXPANSION_TAG_:
                case CollationElementIterator.CE_DIGIT_TAG_:
                    // sCh.delete(0, sCh.length());
                    // sCh.append(ch);
                    // it.setText(sCh.toString());
                    it.setText(UCharacter.toString(ch));
                    while ((CE = it.next()) != CollationElementIterator.NULLORDER) {
                        if (s.primShift < 0 || s.secShift < 0 || s.terShift < 0) {
                            latinOneCEs_[ch] = BAIL_OUT_CE_;
                            latinOneCEs_[latinOneTableLen_ + ch] = BAIL_OUT_CE_;
                            latinOneCEs_[2 * latinOneTableLen_ + ch] = BAIL_OUT_CE_;
                            break;
                        }
                        addLatinOneEntry(ch, CE, s);
                    }
                    break;
                case CollationElementIterator.CE_CONTRACTION_TAG_:
                    // here is the trick
                    // F2 is contraction. We do something very similar to contractions
                    // but have two indices, one in the real contraction table and the
                    // other to where we stuffed things. This hopes that we don't have
                    // many contractions (this should work for latin-1 tables).
                {
                    if ((CE & 0x00FFF000) != 0) {
                        latinOneFailed_ = true;
                        return false;
                    }

                    int UCharOffset = (CE & 0xFFFFFF) - m_contractionOffset_; // getContractionOffset(CE)]

                    CE |= (contractionOffset & 0xFFF) << 12; // insert the offset in latin-1 table

                    latinOneCEs_[ch] = CE;
                    latinOneCEs_[latinOneTableLen_ + ch] = CE;
                    latinOneCEs_[2 * latinOneTableLen_ + ch] = CE;

                    // We're going to jump into contraction table, pick the elements
                    // and use them
                    do {
                        // CE = *(contractionCEs + (UCharOffset - contractionIndex));
                        CE = m_contractionCE_[UCharOffset];
                        if (isSpecial(CE) && getTag(CE) == CollationElementIterator.CE_EXPANSION_TAG_) {
                            int i; /* general counter */
                            // uint32_t *CEOffset = (uint32_t *)image+getExpansionOffset(CE); /* find the offset to
                            // expansion table */
                            int offset = ((CE & 0xFFFFF0) >> 4) - m_expansionOffset_; // it.getExpansionOffset(this,
                            // CE);
                            int size = CE & 0xF; // getExpansionCount(CE);
                            // CE = *CEOffset++;
                            if (size != 0) { /* if there are less than 16 elements in expansion, we don't terminate */
                                for (i = 0; i < size; i++) {
                                    if (s.primShift < 0 || s.secShift < 0 || s.terShift < 0) {
                                        latinOneCEs_[contractionOffset] = BAIL_OUT_CE_;
                                        latinOneCEs_[latinOneTableLen_ + contractionOffset] = BAIL_OUT_CE_;
                                        latinOneCEs_[2 * latinOneTableLen_ + contractionOffset] = BAIL_OUT_CE_;
                                        break;
                                    }
                                    addLatinOneEntry(contractionOffset, m_expansion_[offset + i], s);
                                }
                            } else { /* else, we do */
                                while (m_expansion_[offset] != 0) {
                                    if (s.primShift < 0 || s.secShift < 0 || s.terShift < 0) {
                                        latinOneCEs_[contractionOffset] = BAIL_OUT_CE_;
                                        latinOneCEs_[latinOneTableLen_ + contractionOffset] = BAIL_OUT_CE_;
                                        latinOneCEs_[2 * latinOneTableLen_ + contractionOffset] = BAIL_OUT_CE_;
                                        break;
                                    }
                                    addLatinOneEntry(contractionOffset, m_expansion_[offset++], s);
                                }
                            }
                            contractionOffset++;
                        } else if (!isSpecial(CE)) {
                            addLatinOneEntry(contractionOffset++, CE, s);
                        } else {
                            latinOneCEs_[contractionOffset] = BAIL_OUT_CE_;
                            latinOneCEs_[latinOneTableLen_ + contractionOffset] = BAIL_OUT_CE_;
                            latinOneCEs_[2 * latinOneTableLen_ + contractionOffset] = BAIL_OUT_CE_;
                            contractionOffset++;
                        }
                        UCharOffset++;
                        s.primShift = 24;
                        s.secShift = 24;
                        s.terShift = 24;
                        if (contractionOffset == latinOneTableLen_) { // we need to reallocate
                            resizeLatinOneTable(2 * latinOneTableLen_);
                        }
                    } while (m_contractionIndex_[UCharOffset] != 0xFFFF);
                }
                break;
                case CollationElementIterator.CE_SPEC_PROC_TAG_: {
                    // 0xB7 is a precontext character defined in UCA5.1, a special
                    // handle is implemeted in order to save LatinOne table for
                    // most locales.
                    if (ch == 0xb7) {
                        addLatinOneEntry(ch, CE, s);
                    } else {
                        latinOneFailed_ = true;
                        return false;
                    }
                }
                break;
                default:
                    latinOneFailed_ = true;
                    return false;
                }
            }
        }
        // compact table
        if (contractionOffset < latinOneTableLen_) {
            resizeLatinOneTable(contractionOffset);
        }
        return true;
    }

    private class ContractionInfo {
        int index;
    }

    ContractionInfo m_ContInfo_;

    private int getLatinOneContraction(int strength, int CE, String s) {
        // int strength, int CE, String s, Integer ind) {
        int len = s.length();
        // const UChar *UCharOffset = (UChar *)coll->image+getContractOffset(CE&0xFFF);
        int UCharOffset = (CE & 0xFFF) - m_contractionOffset_;
        int offset = 1;
        int latinOneOffset = (CE & 0x00FFF000) >>> 12;
                                    char schar = 0, tchar = 0;

                                    for (;;) {
                                        /*
                                         * if(len == -1) { if(s[*index] == 0) { // end of string
                                         * return(coll->latinOneCEs[strength*coll->latinOneTableLen+latinOneOffset]); } else { schar = s[*index]; }
                                         * } else {
                                         */
                                        if (m_ContInfo_.index == len) {
                                            return (latinOneCEs_[strength * latinOneTableLen_ + latinOneOffset]);
                                        } else {
                                            schar = s.charAt(m_ContInfo_.index);
                                        }
                                        // }

                                        while (schar > (tchar = m_contractionIndex_[UCharOffset + offset]/** (UCharOffset+offset) */
                                        )) { /* since the contraction codepoints should be ordered, we skip all that are smaller */
                                            offset++;
                                        }

                                        if (schar == tchar) {
                                            m_ContInfo_.index++;
                                            return (latinOneCEs_[strength * latinOneTableLen_ + latinOneOffset + offset]);
                                        } else {
                                            if (schar > ENDOFLATINONERANGE_ /* & 0xFF00 */) {
                                                return BAIL_OUT_CE_;
                                            }
                                            // skip completely ignorables
                                            int isZeroCE = m_trie_.getLeadValue(schar); // UTRIE_GET32_FROM_LEAD(coll->mapping, schar);
                                            if (isZeroCE == 0) { // we have to ignore completely ignorables
                                                m_ContInfo_.index++;
                                                continue;
                                            }

                                            return (latinOneCEs_[strength * latinOneTableLen_ + latinOneOffset]);
                                        }
                                    }
    }

    /**
     * This is a fast strcoll, geared towards text in Latin-1. It supports contractions of size two, French secondaries
     * and case switching. You can use it with strengths primary to tertiary. It does not support shifted and case
     * level. It relies on the table build by setupLatin1Table. If it doesn't understand something, it will go to the
     * regular strcoll.
     */
    private final int compareUseLatin1(String source, String target, int startOffset) {
        int sLen = source.length();
        int tLen = target.length();

        int strength = getStrength();

        int sIndex = startOffset, tIndex = startOffset;
        char sChar = 0, tChar = 0;
        int sOrder = 0, tOrder = 0;

        boolean endOfSource = false;

        // uint32_t *elements = coll->latinOneCEs;

        boolean haveContractions = false; // if we have contractions in our string
        // we cannot do French secondary

        int offset = latinOneTableLen_;

        // Do the primary level
primLoop: 
        for (;;) {
            while (sOrder == 0) { // this loop skips primary ignorables
                // sOrder=getNextlatinOneCE(source);
                if (sIndex == sLen) {
                    endOfSource = true;
                    break;
                }
                sChar = source.charAt(sIndex++); // [sIndex++];
                // }
                if (sChar > ENDOFLATINONERANGE_) { // if we encounter non-latin-1, we bail out
                    // fprintf(stderr, "R");
                    return compareRegular(source, target, startOffset);
                }
                sOrder = latinOneCEs_[sChar];
                if (isSpecial(sOrder)) { // if we got a special
                    // specials can basically be either contractions or bail-out signs. If we get anything
                    // else, we'll bail out anywasy
                    if (getTag(sOrder) == CollationElementIterator.CE_CONTRACTION_TAG_) {
                        m_ContInfo_.index = sIndex;
                        sOrder = getLatinOneContraction(0, sOrder, source);
                        sIndex = m_ContInfo_.index;
                        haveContractions = true; // if there are contractions, we cannot do French secondary
                        // However, if there are contractions in the table, but we always use just one char,
                        // we might be able to do French. This should be checked out.
                    }
                    if (isSpecial(sOrder) /* == UCOL_BAIL_OUT_CE */) {
                        // fprintf(stderr, "S");
                        return compareRegular(source, target, startOffset);
                    }
                }
            }

            while (tOrder == 0) { // this loop skips primary ignorables
                // tOrder=getNextlatinOneCE(target);
                if (tIndex == tLen) {
                    if (endOfSource) {
                        break primLoop;
                    } else {
                        return 1;
                    }
                }
                tChar = target.charAt(tIndex++); // [tIndex++];
                if (tChar > ENDOFLATINONERANGE_) { // if we encounter non-latin-1, we bail out
                    // fprintf(stderr, "R");
                    return compareRegular(source, target, startOffset);
                }
                tOrder = latinOneCEs_[tChar];
                if (isSpecial(tOrder)) {
                    // Handling specials, see the comments for source
                    if (getTag(tOrder) == CollationElementIterator.CE_CONTRACTION_TAG_) {
                        m_ContInfo_.index = tIndex;
                        tOrder = getLatinOneContraction(0, tOrder, target);
                        tIndex = m_ContInfo_.index;
                        haveContractions = true;
                    }
                    if (isSpecial(tOrder)/* == UCOL_BAIL_OUT_CE */) {
                        // fprintf(stderr, "S");
                        return compareRegular(source, target, startOffset);
                    }
                }
            }
            if (endOfSource) { // source is finished, but target is not, say the result.
                return -1;
            }

            if (sOrder == tOrder) { // if we have same CEs, we continue the loop
                sOrder = 0;
                tOrder = 0;
                continue;
            } else {
                // compare current top bytes
                if (((sOrder ^ tOrder) & 0xFF000000) != 0) {
                    // top bytes differ, return difference
                    if (sOrder >>> 8 < tOrder >>> 8) {
                        return -1;
                    } else {
                        return 1;
                    }
                    // instead of return (int32_t)(sOrder>>24)-(int32_t)(tOrder>>24);
                    // since we must return enum value
                }

                // top bytes match, continue with following bytes
                sOrder <<= 8;
                tOrder <<= 8;
            }
        }

        // after primary loop, we definitely know the sizes of strings,
        // so we set it and use simpler loop for secondaries and tertiaries
        // sLen = sIndex; tLen = tIndex;
        if (strength >= SECONDARY) {
            // adjust the table beggining
            // latinOneCEs_ += coll->latinOneTableLen;
            endOfSource = false;

            if (!m_isFrenchCollation_) { // non French
                // This loop is a simplified copy of primary loop
                // at this point we know that whole strings are latin-1, so we don't
                // check for that. We also know that we only have contractions as
                // specials.
                // sIndex = 0; tIndex = 0;
                sIndex = startOffset;
                tIndex = startOffset;
                secLoop: for (;;) {
                    while (sOrder == 0) {
                        if (sIndex == sLen) {
                            endOfSource = true;
                            break;
                        }
                        sChar = source.charAt(sIndex++); // [sIndex++];
                        sOrder = latinOneCEs_[offset + sChar];
                        if (isSpecial(sOrder)) {
                            m_ContInfo_.index = sIndex;
                            sOrder = getLatinOneContraction(1, sOrder, source);
                            sIndex = m_ContInfo_.index;
                        }
                    }

                    while (tOrder == 0) {
                        if (tIndex == tLen) {
                            if (endOfSource) {
                                break secLoop;
                            } else {
                                return 1;
                            }
                        }
                        tChar = target.charAt(tIndex++); // [tIndex++];
                        tOrder = latinOneCEs_[offset + tChar];
                        if (isSpecial(tOrder)) {
                            m_ContInfo_.index = tIndex;
                            tOrder = getLatinOneContraction(1, tOrder, target);
                            tIndex = m_ContInfo_.index;
                        }
                    }
                    if (endOfSource) {
                        return -1;
                    }

                    if (sOrder == tOrder) {
                        sOrder = 0;
                        tOrder = 0;
                        continue;
                    } else {
                        // see primary loop for comments on this
                        if (((sOrder ^ tOrder) & 0xFF000000) != 0) {
                            if (sOrder >>> 8 < tOrder >>> 8) {
                                return -1;
                            } else {
                                return 1;
                            }
                        }
                        sOrder <<= 8;
                        tOrder <<= 8;
                    }
                }
            } else { // French
                if (haveContractions) { // if we have contractions, we have to bail out
                    // since we don't really know how to handle them here
                    return compareRegular(source, target, startOffset);
                }
                // For French, we go backwards
                sIndex = sLen;
                tIndex = tLen;
                secFLoop: for (;;) {
                    while (sOrder == 0) {
                        if (sIndex == startOffset) {
                            endOfSource = true;
                            break;
                        }
                        sChar = source.charAt(--sIndex); // [--sIndex];
                        sOrder = latinOneCEs_[offset + sChar];
                        // don't even look for contractions
                    }

                    while (tOrder == 0) {
                        if (tIndex == startOffset) {
                            if (endOfSource) {
                                break secFLoop;
                            } else {
                                return 1;
                            }
                        }
                        tChar = target.charAt(--tIndex); // [--tIndex];
                        tOrder = latinOneCEs_[offset + tChar];
                        // don't even look for contractions
                    }
                    if (endOfSource) {
                        return -1;
                    }

                    if (sOrder == tOrder) {
                        sOrder = 0;
                        tOrder = 0;
                        continue;
                    } else {
                        // see the primary loop for comments
                        if (((sOrder ^ tOrder) & 0xFF000000) != 0) {
                            if (sOrder >>> 8 < tOrder >>> 8) {
                                return -1;
                            } else {
                                return 1;
                            }
                        }
                        sOrder <<= 8;
                        tOrder <<= 8;
                    }
                }
            }
        }

        if (strength >= TERTIARY) {
            // tertiary loop is the same as secondary (except no French)
            offset += latinOneTableLen_;
            // sIndex = 0; tIndex = 0;
            sIndex = startOffset;
            tIndex = startOffset;
            endOfSource = false;
            for (;;) {
                while (sOrder == 0) {
                    if (sIndex == sLen) {
                        endOfSource = true;
                        break;
                    }
                    sChar = source.charAt(sIndex++); // [sIndex++];
                    sOrder = latinOneCEs_[offset + sChar];
                    if (isSpecial(sOrder)) {
                        m_ContInfo_.index = sIndex;
                        sOrder = getLatinOneContraction(2, sOrder, source);
                        sIndex = m_ContInfo_.index;
                    }
                }
                while (tOrder == 0) {
                    if (tIndex == tLen) {
                        if (endOfSource) {
                            return 0; // if both strings are at the end, they are equal
                        } else {
                            return 1;
                        }
                    }
                    tChar = target.charAt(tIndex++); // [tIndex++];
                    tOrder = latinOneCEs_[offset + tChar];
                    if (isSpecial(tOrder)) {
                        m_ContInfo_.index = tIndex;
                        tOrder = getLatinOneContraction(2, tOrder, target);
                        tIndex = m_ContInfo_.index;
                    }
                }
                if (endOfSource) {
                    return -1;
                }
                if (sOrder == tOrder) {
                    sOrder = 0;
                    tOrder = 0;
                    continue;
                } else {
                    if (((sOrder ^ tOrder) & 0xff000000) != 0) {
                        if (sOrder >>> 8 < tOrder >>> 8) {
                            return -1;
                        } else {
                            return 1;
                        }
                    }
                    sOrder <<= 8;
                    tOrder <<= 8;
                }
            }
        }
        return 0;
    }

    /**
     * Get the version of this collator object.
     * 
     * @return the version object associated with this collator
     * @stable ICU 2.8
     */
    public VersionInfo getVersion() {
        /* RunTime version */
        int rtVersion = VersionInfo.UCOL_RUNTIME_VERSION.getMajor();
        /* Builder version */
        int bdVersion = m_version_.getMajor();

        /*
         * Charset Version. Need to get the version from cnv files makeconv should populate cnv files with version and
         * an api has to be provided in ucnv.h to obtain this version
         */
        int csVersion = 0;

        /* combine the version info */
        int cmbVersion = ((rtVersion << 11) | (bdVersion << 6) | (csVersion)) & 0xFFFF;

        /* Tailoring rules */
        return VersionInfo.getInstance(cmbVersion >> 8, cmbVersion & 0xFF, m_version_.getMinor(),
        UCA_.m_UCA_version_.getMajor());

        // versionInfo[0] = (uint8_t)(cmbVersion>>8);
        // versionInfo[1] = (uint8_t)cmbVersion;
        // versionInfo[2] = coll->image->version[1];
        // versionInfo[3] = coll->UCA->image->UCAVersion[0];
    }

    /**
     * Get the UCA version of this collator object.
     * 
     * @return the version object associated with this collator
     * @stable ICU 2.8
     */
    public VersionInfo getUCAVersion() {
        return UCA_.m_UCA_version_;
    }

    private transient boolean m_reallocLatinOneCEs_;
}
