Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * $Id: StringComparable.java 468655 2006-10-28 07:12:06Z minchau $ */ import java.util.Vector; import java.text.Collator; import java.text.RuleBasedCollator; import java.text.CollationElementIterator; import java.util.Locale; import java.text.CollationKey; /** * International friendly string comparison with case-order * @author Igor Hersht, igorh@ca.ibm.com */ public class StringComparable implements Comparable { public final static int UNKNOWN_CASE = -1; public final static int UPPER_CASE = 1; public final static int LOWER_CASE = 2; private String m_text; private Locale m_locale; private RuleBasedCollator m_collator; private String m_caseOrder; private int m_mask = 0xFFFFFFFF; public StringComparable(final String text, final Locale locale, final Collator collator, final String caseOrder) { m_text = text; m_locale = locale; m_collator = (RuleBasedCollator) collator; m_caseOrder = caseOrder; m_mask = getMask(m_collator.getStrength()); } public final static Comparable getComparator(final String text, final Locale locale, final Collator collator, final String caseOrder) { if ((caseOrder == null) || (caseOrder.length() == 0)) {// no case-order specified return ((RuleBasedCollator) collator).getCollationKey(text); } else { return new StringComparable(text, locale, collator, caseOrder); } } public final String toString() { return m_text; } public int compareTo(Object o) { final String pattern = ((StringComparable) o).toString(); if (m_text.equals(pattern)) {//Code-point equals return 0; } final int savedStrength = m_collator.getStrength(); int comp = 0; // Is there difference more significant than case-order? if (((savedStrength == Collator.PRIMARY) || (savedStrength == Collator.SECONDARY))) { comp = m_collator.compare(m_text, pattern); } else {// more than SECONDARY m_collator.setStrength(Collator.SECONDARY); comp = m_collator.compare(m_text, pattern); m_collator.setStrength(savedStrength); } if (comp != 0) {//Difference more significant than case-order return comp; } // No difference more significant than case-order. // Find case difference comp = getCaseDiff(m_text, pattern); if (comp != 0) { return comp; } else {// No case differences. Less significant difference could exist return m_collator.compare(m_text, pattern); } } private final int getCaseDiff(final String text, final String pattern) { final int savedStrength = m_collator.getStrength(); final int savedDecomposition = m_collator.getDecomposition(); m_collator.setStrength(Collator.TERTIARY);// not to ignore case m_collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION);// corresponds NDF final int diff[] = getFirstCaseDiff(text, pattern, m_locale); m_collator.setStrength(savedStrength);// restore m_collator.setDecomposition(savedDecomposition); //restore if (diff != null) { if ((m_caseOrder).equals("upper-first")) { if (diff[0] == UPPER_CASE) { return -1; } else { return 1; } } else {// lower-first if (diff[0] == LOWER_CASE) { return -1; } else { return 1; } } } else {// No case differences return 0; } } private final int[] getFirstCaseDiff(final String text, final String pattern, final Locale locale) { final CollationElementIterator targIter = m_collator.getCollationElementIterator(text); final CollationElementIterator patIter = m_collator.getCollationElementIterator(pattern); int startTarg = -1; int endTarg = -1; int startPatt = -1; int endPatt = -1; final int done = getElement(CollationElementIterator.NULLORDER); int patternElement = 0, targetElement = 0; boolean getPattern = true, getTarget = true; while (true) { if (getPattern) { startPatt = patIter.getOffset(); patternElement = getElement(patIter.next()); endPatt = patIter.getOffset(); } if ((getTarget)) { startTarg = targIter.getOffset(); targetElement = getElement(targIter.next()); endTarg = targIter.getOffset(); } getTarget = getPattern = true; if ((patternElement == done) || (targetElement == done)) { return null; } else if (targetElement == 0) { getPattern = false; } else if (patternElement == 0) { getTarget = false; } else if (targetElement != patternElement) {// mismatch if ((startPatt < endPatt) && (startTarg < endTarg)) { final String subText = text.substring(startTarg, endTarg); final String subPatt = pattern.substring(startPatt, endPatt); final String subTextUp = subText.toUpperCase(locale); final String subPattUp = subPatt.toUpperCase(locale); if (m_collator.compare(subTextUp, subPattUp) != 0) { // not case diffference continue; } int diff[] = { UNKNOWN_CASE, UNKNOWN_CASE }; if (m_collator.compare(subText, subTextUp) == 0) { diff[0] = UPPER_CASE; } else if (m_collator.compare(subText, subText.toLowerCase(locale)) == 0) { diff[0] = LOWER_CASE; } if (m_collator.compare(subPatt, subPattUp) == 0) { diff[1] = UPPER_CASE; } else if (m_collator.compare(subPatt, subPatt.toLowerCase(locale)) == 0) { diff[1] = LOWER_CASE; } if (((diff[0] == UPPER_CASE) && (diff[1] == LOWER_CASE)) || ((diff[0] == LOWER_CASE) && (diff[1] == UPPER_CASE))) { return diff; } else {// not case diff continue; } } else { continue; } } } } // Return a mask for the part of the order we're interested in private static final int getMask(final int strength) { switch (strength) { case Collator.PRIMARY: return 0xFFFF0000; case Collator.SECONDARY: return 0xFFFFFF00; default: return 0xFFFFFFFF; } } //get collation element with given strength // from the element with max strength private final int getElement(int maxStrengthElement) { return (maxStrengthElement & m_mask); } }//StringComparable