|
|
|
|
|
*/ |
|
/* |
|
* 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. |
|
*/ |
|
|
|
package com.sun.org.apache.xml.internal.utils; |
|
|
|
import java.text.CollationElementIterator; |
|
import java.text.Collator; |
|
import java.text.RuleBasedCollator; |
|
import java.util.Locale; |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public class StringComparable implements Comparable<StringComparable> { |
|
|
|
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()); |
|
} |
|
|
|
@SuppressWarnings({"rawtypes", "unchecked"}) |
|
public final static Comparable getComparator( final String text, final Locale locale, |
|
final Collator collator, final String caseOrder){ |
|
if((caseOrder == null) ||(caseOrder.length() == 0)){ |
|
return ((RuleBasedCollator)collator).getCollationKey(text); |
|
}else{ |
|
return new StringComparable(text, locale, collator, caseOrder); |
|
} |
|
} |
|
|
|
public final String toString(){return m_text;} |
|
|
|
public int compareTo(StringComparable o) { |
|
final String pattern = o.toString(); |
|
if(m_text.equals(pattern)){ |
|
return 0; |
|
} |
|
final int savedStrength = m_collator.getStrength(); |
|
int comp = 0; |
|
|
|
if(((savedStrength == Collator.PRIMARY) || (savedStrength == Collator.SECONDARY))){ |
|
comp = m_collator.compare(m_text, pattern ); |
|
}else{ |
|
m_collator.setStrength(Collator.SECONDARY); |
|
comp = m_collator.compare(m_text, pattern ); |
|
m_collator.setStrength(savedStrength); |
|
} |
|
if(comp != 0){ |
|
return comp ; |
|
} |
|
|
|
// No difference more significant than case-order. |
|
|
|
comp = getCaseDiff(m_text, pattern); |
|
if(comp != 0){ |
|
return comp; |
|
}else{ |
|
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); |
|
m_collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION ); |
|
|
|
final int diff[] =getFirstCaseDiff (text, pattern, m_locale); |
|
m_collator.setStrength(savedStrength); |
|
m_collator.setDecomposition(savedDecomposition); |
|
if(diff != null){ |
|
if((m_caseOrder).equals("upper-first")){ |
|
if(diff[0] == UPPER_CASE){ |
|
return -1; |
|
}else{ |
|
return 1; |
|
} |
|
}else{ |
|
if(diff[0] == LOWER_CASE){ |
|
return -1; |
|
}else{ |
|
return 1; |
|
} |
|
} |
|
}else{ |
|
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) { |
|
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){ |
|
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{ |
|
continue; |
|
} |
|
}else{ |
|
continue; |
|
} |
|
|
|
} |
|
} |
|
|
|
} |
|
|
|
|
|
|
|
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 |
|
|
|
private final int getElement(int maxStrengthElement){ |
|
|
|
return (maxStrengthElement & m_mask); |
|
} |
|
|
|
}//StringComparable |