KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xalan > xsltc > dom > NodeSortRecord


1 /*
2  * Copyright 2001-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: NodeSortRecord.java,v 1.19 2004/02/27 01:58:29 zongaro Exp $
18  */

19
20 package org.apache.xalan.xsltc.dom;
21
22 import java.text.CollationKey JavaDoc;
23 import java.text.Collator JavaDoc;
24 import java.util.Locale JavaDoc;
25
26 import org.apache.xalan.xsltc.CollatorFactory;
27 import org.apache.xalan.xsltc.DOM;
28 import org.apache.xalan.xsltc.TransletException;
29 import org.apache.xalan.xsltc.runtime.AbstractTranslet;
30 import org.apache.xml.utils.StringComparable;
31
32 /**
33  * Base class for sort records containing application specific sort keys
34  */

35 public abstract class NodeSortRecord {
36     public static final int COMPARE_STRING = 0;
37     public static final int COMPARE_NUMERIC = 1;
38
39     public static final int COMPARE_ASCENDING = 0;
40     public static final int COMPARE_DESCENDING = 1;
41
42     /**
43      * A reference to a collator. May be updated by subclass if the stylesheet
44      * specifies a different language (will be updated iff _locale is updated).
45      * @deprecated This field continues to exist for binary compatibility.
46      * New code should not refer to it.
47      */

48     private static final Collator JavaDoc DEFAULT_COLLATOR = Collator.getInstance();
49
50     /**
51      * A reference to the first Collator
52      * @deprecated This field continues to exist for binary compatibility.
53      * New code should not refer to it.
54      */

55     protected Collator JavaDoc _collator = DEFAULT_COLLATOR;
56     protected Collator JavaDoc[] _collators;
57
58     /**
59      * A locale field that might be set by an instance of a subclass.
60      * @deprecated This field continues to exist for binary compatibility.
61      * New code should not refer to it.
62      */

63     protected Locale JavaDoc _locale;
64
65     protected CollatorFactory _collatorFactory;
66
67     protected SortSettings _settings;
68
69     private DOM _dom = null;
70     private int _node; // The position in the current iterator
71
private int _last = 0; // Number of nodes in the current iterator
72
private int _scanned = 0; // Number of key levels extracted from DOM
73

74     private Object JavaDoc[] _values; // Contains Comparable objects
75

76     /**
77      * This constructor is run by a call to ClassLoader in the
78      * makeNodeSortRecord method in the NodeSortRecordFactory class. Since we
79      * cannot pass any parameters to the constructor in that case we just set
80      * the default values here and wait for new values through initialize().
81      */

82     public NodeSortRecord(int node) {
83     _node = node;
84     }
85
86     public NodeSortRecord() {
87         this(0);
88     }
89
90     /**
91      * This method allows the caller to set the values that could not be passed
92      * to the default constructor.
93      */

94     public final void initialize(int node, int last, DOM dom,
95          SortSettings settings)
96         throws TransletException
97     {
98     _dom = dom;
99     _node = node;
100     _last = last;
101         _settings = settings;
102
103         int levels = settings.getSortOrders().length;
104     _values = new Object JavaDoc[levels];
105   
106     // -- W. Eliot Kimber (eliot@isogen.com)
107
String JavaDoc colFactClassname =
108         System.getProperty("org.apache.xalan.xsltc.COLLATOR_FACTORY");
109
110         if (colFactClassname != null) {
111             try {
112                 Object JavaDoc candObj = ObjectFactory.findProviderClass(
113                     colFactClassname, ObjectFactory.findClassLoader(), true);
114                 _collatorFactory = (CollatorFactory)candObj;
115             } catch (ClassNotFoundException JavaDoc e) {
116                 throw new TransletException(e);
117             }
118             Locale JavaDoc[] locales = settings.getLocales();
119             _collators = new Collator JavaDoc[levels];
120             for (int i = 0; i < levels; i++){
121                 _collators[i] = _collatorFactory.getCollator(locales[i]);
122             }
123             _collator = _collators[0];
124         } else {
125             _collators = settings.getCollators();
126             _collator = _collators[0];
127         }
128     }
129
130     /**
131      * Returns the node for this sort object
132      */

133     public final int getNode() {
134     return _node;
135     }
136
137     /**
138      *
139      */

140     public final int compareDocOrder(NodeSortRecord other) {
141     return _node - other._node;
142     }
143
144     /**
145      * Get the string or numeric value of a specific level key for this sort
146      * element. The value is extracted from the DOM if it is not already in
147      * our sort key vector.
148      */

149     private final Comparable JavaDoc stringValue(int level) {
150         // Get value from our array if possible
151
if (_scanned <= level) {
152             AbstractTranslet translet = _settings.getTranslet();
153             Locale JavaDoc[] locales = _settings.getLocales();
154             String JavaDoc[] caseOrder = _settings.getCaseOrders();
155
156             // Get value from DOM if accessed for the first time
157
final String JavaDoc str = extractValueFromDOM(_dom, _node, level,
158                                translet, _last);
159             final Comparable JavaDoc key =
160                 StringComparable.getComparator(str, locales[level],
161                                                _collators[level],
162                                                caseOrder[level]);
163             _values[_scanned++] = key;
164             return(key);
165         }
166         return((Comparable JavaDoc)_values[level]);
167   }
168     
169     private final Double JavaDoc numericValue(int level) {
170     // Get value from our vector if possible
171
if (_scanned <= level) {
172             AbstractTranslet translet = _settings.getTranslet();
173
174         // Get value from DOM if accessed for the first time
175
final String JavaDoc str = extractValueFromDOM(_dom, _node, level,
176                            translet, _last);
177         Double JavaDoc num;
178         try {
179         num = new Double JavaDoc(str);
180         }
181         // Treat number as NaN if it cannot be parsed as a double
182
catch (NumberFormatException JavaDoc e) {
183         num = new Double JavaDoc(Double.NEGATIVE_INFINITY);
184         }
185         _values[_scanned++] = num;
186         return(num);
187     }
188     return((Double JavaDoc)_values[level]);
189     }
190
191     /**
192      * Compare this sort element to another. The first level is checked first,
193      * and we proceed to the next level only if the first level keys are
194      * identical (and so the key values may not even be extracted from the DOM)
195      *
196      * !!!!MUST OPTIMISE - THIS IS REALLY, REALLY SLOW!!!!
197      */

198     public int compareTo(NodeSortRecord other) {
199     int cmp, level;
200         int[] sortOrder = _settings.getSortOrders();
201         int levels = _settings.getSortOrders().length;
202         int[] compareTypes = _settings.getTypes();
203
204     for (level = 0; level < levels; level++) {
205         // Compare the two nodes either as numeric or text values
206
if (compareTypes[level] == COMPARE_NUMERIC) {
207         final Double JavaDoc our = numericValue(level);
208         final Double JavaDoc their = other.numericValue(level);
209         cmp = our.compareTo(their);
210         }
211         else {
212         final Comparable JavaDoc our = stringValue(level);
213         final Comparable JavaDoc their = other.stringValue(level);
214         cmp = our.compareTo(their);
215         }
216         
217         // Return inverse compare value if inverse sort order
218
if (cmp != 0) {
219         return sortOrder[level] == COMPARE_DESCENDING ? 0 - cmp : cmp;
220         }
221     }
222     // Compare based on document order if all sort keys are equal
223
return(_node - other._node);
224     }
225
226     /**
227      * Returns the array of Collators used for text comparisons in this object.
228      * May be overridden by inheriting classes
229      */

230     public Collator JavaDoc[] getCollator() {
231     return _collators;
232     }
233
234     /**
235      * Extract the sort value for a level of this key.
236      */

237     public abstract String JavaDoc extractValueFromDOM(DOM dom, int current, int level,
238                            AbstractTranslet translet,
239                            int last);
240
241 }
242
Popular Tags