KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xml > utils > StringComparable


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 /*
17  * $Id: StringComparable.java,v 1.2 2004/02/17 04:21:14 minchau Exp $
18  */

19
20 package org.apache.xml.utils;
21
22 import java.util.Vector JavaDoc;
23 import java.text.Collator JavaDoc;
24 import java.text.RuleBasedCollator JavaDoc;
25 import java.text.CollationElementIterator JavaDoc;
26 import java.util.Locale JavaDoc;
27 import java.text.CollationKey JavaDoc;
28
29
30 /**
31 * International friendly string comparison with case-order
32  * @author Igor Hersht, igorh@ca.ibm.com
33 */

34 public class StringComparable implements Comparable JavaDoc {
35     
36      public final static int UNKNOWN_CASE = -1;
37      public final static int UPPER_CASE = 1;
38      public final static int LOWER_CASE = 2;
39      
40      private String JavaDoc m_text;
41      private Locale JavaDoc m_locale;
42      private RuleBasedCollator JavaDoc m_collator;
43      private String JavaDoc m_caseOrder;
44      private int m_mask = 0xFFFFFFFF;
45      
46     public StringComparable(final String JavaDoc text, final Locale JavaDoc locale, final Collator JavaDoc collator, final String JavaDoc caseOrder){
47          m_text = text;
48          m_locale = locale;
49          m_collator = (RuleBasedCollator JavaDoc)collator;
50          m_caseOrder = caseOrder;
51          m_mask = getMask(m_collator.getStrength());
52     }
53   
54    public final static Comparable JavaDoc getComparator( final String JavaDoc text, final Locale JavaDoc locale, final Collator JavaDoc collator, final String JavaDoc caseOrder){
55        if((caseOrder == null) ||(caseOrder.length() == 0)){// no case-order specified
56
return ((RuleBasedCollator JavaDoc)collator).getCollationKey(text);
57        }else{
58             return new StringComparable(text, locale, collator, caseOrder);
59        }
60    }
61    
62    public final String JavaDoc toString(){return m_text;}
63    
64    public int compareTo(Object JavaDoc o) {
65    final String JavaDoc pattern = ((StringComparable)o).toString();
66    if(m_text.equals(pattern)){//Code-point equals
67
return 0;
68    }
69    final int savedStrength = m_collator.getStrength();
70    int comp = 0;
71       // Is there difference more significant than case-order?
72
if(((savedStrength == Collator.PRIMARY) || (savedStrength == Collator.SECONDARY))){
73          comp = m_collator.compare(m_text, pattern );
74      }else{// more than SECONDARY
75
m_collator.setStrength(Collator.SECONDARY);
76          comp = m_collator.compare(m_text, pattern );
77          m_collator.setStrength(savedStrength);
78      }
79      if(comp != 0){//Difference more significant than case-order
80
return comp ;
81      }
82         
83       // No difference more significant than case-order.
84
// Find case difference
85
comp = getCaseDiff(m_text, pattern);
86        if(comp != 0){
87            return comp;
88        }else{// No case differences. Less significant difference could exist
89
return m_collator.compare(m_text, pattern );
90        }
91   }
92   
93  
94   private final int getCaseDiff (final String JavaDoc text, final String JavaDoc pattern){
95      final int savedStrength = m_collator.getStrength();
96      final int savedDecomposition = m_collator.getDecomposition();
97      m_collator.setStrength(Collator.TERTIARY);// not to ignore case
98
m_collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION );// corresponds NDF
99

100     final int diff[] =getFirstCaseDiff (text, pattern, m_locale);
101     m_collator.setStrength(savedStrength);// restore
102
m_collator.setDecomposition(savedDecomposition); //restore
103
if(diff != null){
104        if((m_caseOrder).equals("upper-first")){
105             if(diff[0] == UPPER_CASE){
106                 return -1;
107             }else{
108                 return 1;
109             }
110        }else{// lower-first
111
if(diff[0] == LOWER_CASE){
112                 return -1;
113             }else{
114                 return 1;
115             }
116        }
117    }else{// No case differences
118
return 0;
119    }
120     
121   }
122   
123    
124     
125   private final int[] getFirstCaseDiff(final String JavaDoc text, final String JavaDoc pattern, final Locale JavaDoc locale){
126         
127         final CollationElementIterator JavaDoc targIter = m_collator.getCollationElementIterator(text);
128         final CollationElementIterator JavaDoc patIter = m_collator.getCollationElementIterator(pattern);
129         int startTarg = -1;
130         int endTarg = -1;
131         int startPatt = -1;
132         int endPatt = -1;
133         final int done = getElement(CollationElementIterator.NULLORDER);
134         int patternElement = 0, targetElement = 0;
135         boolean getPattern = true, getTarget = true;
136         
137         while (true) {
138             if (getPattern){
139                  startPatt = patIter.getOffset();
140                  patternElement = getElement(patIter.next());
141                  endPatt = patIter.getOffset();
142             }
143             if ((getTarget)){
144                  startTarg = targIter.getOffset();
145                  targetElement = getElement(targIter.next());
146                  endTarg = targIter.getOffset();
147             }
148             getTarget = getPattern = true;
149             if ((patternElement == done) ||( targetElement == done)) {
150                 return null;
151             } else if (targetElement == 0) {
152               getPattern = false;
153             } else if (patternElement == 0) {
154               getTarget = false;
155             } else if (targetElement != patternElement) {// mismatch
156
if((startPatt < endPatt) && (startTarg < endTarg)){
157                     final String JavaDoc subText = text.substring(startTarg, endTarg);
158                     final String JavaDoc subPatt = pattern.substring(startPatt, endPatt);
159                     final String JavaDoc subTextUp = subText.toUpperCase(locale);
160                     final String JavaDoc subPattUp = subPatt.toUpperCase(locale);
161                     if(m_collator.compare(subTextUp, subPattUp) != 0){ // not case diffference
162
continue;
163                     }
164                     
165                     int diff[] = {UNKNOWN_CASE, UNKNOWN_CASE};
166                     if(m_collator.compare(subText, subTextUp) == 0){
167                         diff[0] = UPPER_CASE;
168                     }else if(m_collator.compare(subText, subText.toLowerCase(locale)) == 0){
169                        diff[0] = LOWER_CASE;
170                     }
171                     if(m_collator.compare(subPatt, subPattUp) == 0){
172                         diff[1] = UPPER_CASE;
173                     }else if(m_collator.compare(subPatt, subPatt.toLowerCase(locale)) == 0){
174                        diff[1] = LOWER_CASE;
175                     }
176                     
177                     if(((diff[0] == UPPER_CASE) && ( diff[1] == LOWER_CASE)) ||
178                        ((diff[0] == LOWER_CASE) && ( diff[1] == UPPER_CASE))){
179                         return diff;
180                     }else{// not case diff
181
continue;
182                     }
183                 }else{
184                     continue;
185                 }
186                     
187            }
188         }
189                            
190   }
191   
192   
193  // Return a mask for the part of the order we're interested in
194
private static final int getMask(final int strength) {
195         switch (strength) {
196             case Collator.PRIMARY:
197                 return 0xFFFF0000;
198             case Collator.SECONDARY:
199                 return 0xFFFFFF00;
200             default:
201                 return 0xFFFFFFFF;
202         }
203     }
204     //get collation element with given strength
205
// from the element with max strength
206
private final int getElement(int maxStrengthElement){
207     
208     return (maxStrengthElement & m_mask);
209   }
210
211 }//StringComparable
212

213
214
Popular Tags