~vcs-imports/xena/trunk

« back to all changes in this revision

Viewing changes to ext/src/xalan-j_2_7_1/src/org/apache/xml/utils/StringComparable.java

  • Committer: matthewoliver
  • Date: 2009-12-10 03:18:07 UTC
  • Revision ID: vcs-imports@canonical.com-20091210031807-l086qguzdlljtkl9
Merged Xena Testing into Xena Stable for the Xena 5 release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Licensed to the Apache Software Foundation (ASF) under one
 
3
 * or more contributor license agreements. See the NOTICE file
 
4
 * distributed with this work for additional information
 
5
 * regarding copyright ownership. The ASF licenses this file
 
6
 * to you under the Apache License, Version 2.0 (the  "License");
 
7
 * you may not use this file except in compliance with the License.
 
8
 * You may obtain a copy of the License at
 
9
 *
 
10
 *     http://www.apache.org/licenses/LICENSE-2.0
 
11
 *
 
12
 * Unless required by applicable law or agreed to in writing, software
 
13
 * distributed under the License is distributed on an "AS IS" BASIS,
 
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
15
 * See the License for the specific language governing permissions and
 
16
 * limitations under the License.
 
17
 */
 
18
/*
 
19
 * $Id: StringComparable.java,v 1.2 2009/12/10 03:18:23 matthewoliver Exp $
 
20
 */
 
21
 
 
22
package org.apache.xml.utils;
 
23
 
 
24
import java.util.Vector;
 
25
import java.text.Collator;
 
26
import java.text.RuleBasedCollator;
 
27
import java.text.CollationElementIterator;
 
28
import java.util.Locale;
 
29
import java.text.CollationKey;
 
30
 
 
31
 
 
32
/**
 
33
* International friendly string comparison with case-order
 
34
 * @author Igor Hersht, igorh@ca.ibm.com
 
35
*/
 
36
public class StringComparable implements Comparable  {
 
37
    
 
38
     public final static int UNKNOWN_CASE = -1;
 
39
     public final static int UPPER_CASE = 1;
 
40
     public final static int LOWER_CASE = 2;
 
41
     
 
42
     private  String m_text;
 
43
     private  Locale m_locale;
 
44
     private RuleBasedCollator m_collator;
 
45
     private String m_caseOrder;
 
46
     private int m_mask = 0xFFFFFFFF; 
 
47
     
 
48
    public StringComparable(final String text, final Locale locale, final Collator collator, final String caseOrder){
 
49
         m_text =  text;
 
50
         m_locale = locale;
 
51
         m_collator = (RuleBasedCollator)collator;
 
52
         m_caseOrder = caseOrder;
 
53
         m_mask = getMask(m_collator.getStrength());
 
54
    }
 
55
  
 
56
   public final static Comparable getComparator( final String text, final Locale locale, final Collator collator, final String caseOrder){
 
57
       if((caseOrder == null) ||(caseOrder.length() == 0)){// no case-order specified
 
58
            return  ((RuleBasedCollator)collator).getCollationKey(text);
 
59
       }else{
 
60
            return new StringComparable(text, locale, collator, caseOrder);
 
61
       }       
 
62
   }
 
63
   
 
64
   public final String toString(){return m_text;}
 
65
   
 
66
   public int compareTo(Object o) {
 
67
   final String pattern = ((StringComparable)o).toString();
 
68
   if(m_text.equals(pattern)){//Code-point equals 
 
69
      return 0;
 
70
   }
 
71
   final int savedStrength = m_collator.getStrength(); 
 
72
   int comp = 0;
 
73
      // Is there difference more significant than case-order?     
 
74
     if(((savedStrength == Collator.PRIMARY) || (savedStrength == Collator.SECONDARY))){  
 
75
         comp = m_collator.compare(m_text, pattern );     
 
76
     }else{// more than SECONDARY
 
77
         m_collator.setStrength(Collator.SECONDARY);
 
78
         comp = m_collator.compare(m_text, pattern );
 
79
         m_collator.setStrength(savedStrength);
 
80
     }
 
81
     if(comp != 0){//Difference more significant than case-order 
 
82
        return comp ; 
 
83
     }      
 
84
        
 
85
      // No difference more significant than case-order.     
 
86
      // Find case difference
 
87
       comp = getCaseDiff(m_text, pattern);
 
88
       if(comp != 0){  
 
89
           return comp;
 
90
       }else{// No case differences. Less significant difference could exist 
 
91
            return m_collator.compare(m_text, pattern );
 
92
       }      
 
93
  }
 
94
  
 
95
 
 
96
  private final int getCaseDiff (final String text, final String pattern){
 
97
     final int savedStrength = m_collator.getStrength();
 
98
     final int savedDecomposition = m_collator.getDecomposition();
 
99
     m_collator.setStrength(Collator.TERTIARY);// not to ignore case  
 
100
     m_collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION );// corresponds NDF
 
101
     
 
102
    final int diff[] =getFirstCaseDiff (text, pattern, m_locale);
 
103
    m_collator.setStrength(savedStrength);// restore
 
104
    m_collator.setDecomposition(savedDecomposition); //restore
 
105
    if(diff != null){  
 
106
       if((m_caseOrder).equals("upper-first")){
 
107
            if(diff[0] == UPPER_CASE){
 
108
                return -1;
 
109
            }else{
 
110
                return 1;
 
111
            }
 
112
       }else{// lower-first
 
113
            if(diff[0] == LOWER_CASE){
 
114
                return -1;
 
115
            }else{
 
116
                return 1;
 
117
            }
 
118
       }
 
119
   }else{// No case differences
 
120
        return 0;
 
121
   }
 
122
    
 
123
  }
 
124
  
 
125
   
 
126
    
 
127
  private final int[] getFirstCaseDiff(final String text, final String pattern, final Locale locale){
 
128
        
 
129
        final CollationElementIterator targIter = m_collator.getCollationElementIterator(text);
 
130
        final CollationElementIterator patIter = m_collator.getCollationElementIterator(pattern);  
 
131
        int startTarg = -1;
 
132
        int endTarg = -1;
 
133
        int startPatt = -1;
 
134
        int endPatt = -1;
 
135
        final int done = getElement(CollationElementIterator.NULLORDER);
 
136
        int patternElement = 0, targetElement = 0;
 
137
        boolean getPattern = true, getTarget = true;
 
138
        
 
139
        while (true) { 
 
140
            if (getPattern){
 
141
                 startPatt = patIter.getOffset();
 
142
                 patternElement = getElement(patIter.next());
 
143
                 endPatt = patIter.getOffset();
 
144
            }
 
145
            if ((getTarget)){               
 
146
                 startTarg  = targIter.getOffset(); 
 
147
                 targetElement   = getElement(targIter.next()); 
 
148
                 endTarg  = targIter.getOffset();
 
149
            }
 
150
            getTarget = getPattern = true;                          
 
151
            if ((patternElement == done) ||( targetElement == done)) {
 
152
                return null;                      
 
153
            } else if (targetElement == 0) {
 
154
              getPattern = false;           
 
155
            } else if (patternElement == 0) {
 
156
              getTarget = false;           
 
157
            } else if (targetElement != patternElement) {// mismatch
 
158
                if((startPatt < endPatt) && (startTarg < endTarg)){
 
159
                    final String  subText = text.substring(startTarg, endTarg);
 
160
                    final String  subPatt = pattern.substring(startPatt, endPatt);
 
161
                    final String  subTextUp = subText.toUpperCase(locale);
 
162
                    final String  subPattUp = subPatt.toUpperCase(locale);
 
163
                    if(m_collator.compare(subTextUp, subPattUp) != 0){ // not case diffference
 
164
                        continue;
 
165
                    }
 
166
                    
 
167
                    int diff[] = {UNKNOWN_CASE, UNKNOWN_CASE};
 
168
                    if(m_collator.compare(subText, subTextUp) == 0){
 
169
                        diff[0] = UPPER_CASE;
 
170
                    }else if(m_collator.compare(subText, subText.toLowerCase(locale)) == 0){
 
171
                       diff[0] = LOWER_CASE; 
 
172
                    }
 
173
                    if(m_collator.compare(subPatt, subPattUp) == 0){
 
174
                        diff[1] = UPPER_CASE;
 
175
                    }else if(m_collator.compare(subPatt, subPatt.toLowerCase(locale)) == 0){
 
176
                       diff[1] = LOWER_CASE; 
 
177
                    }
 
178
                    
 
179
                    if(((diff[0] == UPPER_CASE) && ( diff[1] == LOWER_CASE)) ||
 
180
                       ((diff[0] == LOWER_CASE) && ( diff[1] == UPPER_CASE))){        
 
181
                        return diff;
 
182
                    }else{// not case diff
 
183
                      continue; 
 
184
                    }  
 
185
                }else{
 
186
                    continue; 
 
187
                }
 
188
                    
 
189
           }
 
190
        }
 
191
                           
 
192
  }
 
193
  
 
194
  
 
195
 // Return a mask for the part of the order we're interested in
 
196
    private static final int getMask(final int strength) {
 
197
        switch (strength) {
 
198
            case Collator.PRIMARY:
 
199
                return 0xFFFF0000;
 
200
            case Collator.SECONDARY:
 
201
                return 0xFFFFFF00;
 
202
            default: 
 
203
                return 0xFFFFFFFF;
 
204
        }
 
205
    }
 
206
    //get collation element with given strength
 
207
    // from the element with max strength
 
208
  private final int getElement(int maxStrengthElement){
 
209
    
 
210
    return (maxStrengthElement & m_mask);
 
211
  }  
 
212
 
 
213
}//StringComparable 
 
214
 
 
215