author | joehw |
Wed, 04 Oct 2017 10:54:18 -0700 | |
changeset 47312 | d4f959806fe9 |
parent 47216 | 71c04702a3d5 |
child 48409 | 5ab69533994b |
permissions | -rw-r--r-- |
12005 | 1 |
/* |
45490 | 2 |
* Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. |
47312 | 3 |
* @LastModified: Sep 2017 |
12005 | 4 |
*/ |
5 |
/* |
|
33349 | 6 |
* Licensed to the Apache Software Foundation (ASF) under one or more |
7 |
* contributor license agreements. See the NOTICE file distributed with |
|
8 |
* this work for additional information regarding copyright ownership. |
|
9 |
* The ASF licenses this file to You under the Apache License, Version 2.0 |
|
10 |
* (the "License"); you may not use this file except in compliance with |
|
11 |
* the License. You may obtain a copy of the License at |
|
12005 | 12 |
* |
13 |
* http://www.apache.org/licenses/LICENSE-2.0 |
|
14 |
* |
|
15 |
* Unless required by applicable law or agreed to in writing, software |
|
16 |
* distributed under the License is distributed on an "AS IS" BASIS, |
|
17 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
18 |
* See the License for the specific language governing permissions and |
|
19 |
* limitations under the License. |
|
20 |
*/ |
|
21 |
/* |
|
22 |
* $Id: BasisLibrary.java,v 1.6 2006/06/20 21:51:58 spericas Exp $ |
|
23 |
*/ |
|
24 |
||
25 |
package com.sun.org.apache.xalan.internal.xsltc.runtime; |
|
26 |
||
47312 | 27 |
import com.sun.org.apache.xalan.internal.xsltc.DOM; |
28 |
import com.sun.org.apache.xalan.internal.xsltc.Translet; |
|
29 |
import com.sun.org.apache.xalan.internal.xsltc.dom.AbsoluteIterator; |
|
30 |
import com.sun.org.apache.xalan.internal.xsltc.dom.ArrayNodeListIterator; |
|
31 |
import com.sun.org.apache.xalan.internal.xsltc.dom.DOMAdapter; |
|
32 |
import com.sun.org.apache.xalan.internal.xsltc.dom.MultiDOM; |
|
33 |
import com.sun.org.apache.xalan.internal.xsltc.dom.SingletonIterator; |
|
34 |
import com.sun.org.apache.xalan.internal.xsltc.dom.StepIterator; |
|
35 |
import com.sun.org.apache.xml.internal.dtm.Axis; |
|
36 |
import com.sun.org.apache.xml.internal.dtm.DTM; |
|
37 |
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; |
|
38 |
import com.sun.org.apache.xml.internal.dtm.DTMManager; |
|
39 |
import com.sun.org.apache.xml.internal.dtm.ref.DTMDefaultBase; |
|
40 |
import com.sun.org.apache.xml.internal.dtm.ref.DTMNodeProxy; |
|
41 |
import com.sun.org.apache.xml.internal.serializer.NamespaceMappings; |
|
42 |
import com.sun.org.apache.xml.internal.serializer.SerializationHandler; |
|
43 |
import com.sun.org.apache.xml.internal.utils.XML11Char; |
|
12005 | 44 |
import java.text.DecimalFormat; |
45 |
import java.text.DecimalFormatSymbols; |
|
46 |
import java.text.FieldPosition; |
|
47 |
import java.text.MessageFormat; |
|
48 |
import java.text.NumberFormat; |
|
49 |
import java.util.Locale; |
|
50 |
import java.util.ResourceBundle; |
|
41623
d32a755d06d1
8167179: Make XSL generated namespace prefixes local to transformation process
aefimov
parents:
33349
diff
changeset
|
51 |
import java.util.concurrent.atomic.AtomicInteger; |
12005 | 52 |
import javax.xml.transform.dom.DOMSource; |
47312 | 53 |
import jdk.xml.internal.SecuritySupport; |
54 |
import org.w3c.dom.Attr; |
|
12005 | 55 |
import org.w3c.dom.DOMException; |
56 |
import org.w3c.dom.Document; |
|
12458 | 57 |
import org.w3c.dom.Element; |
12005 | 58 |
import org.w3c.dom.NodeList; |
59 |
import org.xml.sax.SAXException; |
|
60 |
||
61 |
/** |
|
62 |
* Standard XSLT functions. All standard functions expect the current node |
|
63 |
* and the DOM as their last two arguments. |
|
64 |
*/ |
|
65 |
public final class BasisLibrary { |
|
66 |
||
67 |
private final static String EMPTYSTRING = ""; |
|
68 |
||
69 |
/** |
|
70 |
* Re-use a single instance of StringBuffer (per thread) in the basis library. |
|
71 |
* StringBuilder is better, however, DecimalFormat only accept StringBuffer |
|
72 |
*/ |
|
73 |
private static final ThreadLocal<StringBuilder> threadLocalStringBuilder = |
|
74 |
new ThreadLocal<StringBuilder> () { |
|
75 |
@Override protected StringBuilder initialValue() { |
|
76 |
return new StringBuilder(); |
|
77 |
} |
|
78 |
}; |
|
79 |
||
80 |
/** |
|
81 |
* ThreadLocal for StringBuffer used |
|
82 |
*/ |
|
83 |
private static final ThreadLocal<StringBuffer> threadLocalStringBuffer = |
|
84 |
new ThreadLocal<StringBuffer> () { |
|
85 |
@Override protected StringBuffer initialValue() { |
|
86 |
return new StringBuffer(); |
|
87 |
} |
|
88 |
}; |
|
89 |
||
90 |
/** |
|
91 |
* Standard function count(node-set) |
|
92 |
*/ |
|
93 |
public static int countF(DTMAxisIterator iterator) { |
|
94 |
return(iterator.getLast()); |
|
95 |
} |
|
96 |
||
97 |
/** |
|
98 |
* Standard function position() |
|
99 |
* @deprecated This method exists only for backwards compatibility with old |
|
100 |
* translets. New code should not reference it. |
|
101 |
*/ |
|
45490 | 102 |
@Deprecated |
12005 | 103 |
public static int positionF(DTMAxisIterator iterator) { |
104 |
return iterator.isReverse() |
|
105 |
? iterator.getLast() - iterator.getPosition() + 1 |
|
106 |
: iterator.getPosition(); |
|
107 |
} |
|
108 |
||
109 |
/** |
|
110 |
* XSLT Standard function sum(node-set). |
|
111 |
* stringToDouble is inlined |
|
112 |
*/ |
|
113 |
public static double sumF(DTMAxisIterator iterator, DOM dom) { |
|
114 |
try { |
|
115 |
double result = 0.0; |
|
116 |
int node; |
|
117 |
while ((node = iterator.next()) != DTMAxisIterator.END) { |
|
118 |
result += Double.parseDouble(dom.getStringValueX(node)); |
|
119 |
} |
|
120 |
return result; |
|
121 |
} |
|
122 |
catch (NumberFormatException e) { |
|
123 |
return Double.NaN; |
|
124 |
} |
|
125 |
} |
|
126 |
||
127 |
/** |
|
128 |
* XSLT Standard function string() |
|
129 |
*/ |
|
130 |
public static String stringF(int node, DOM dom) { |
|
131 |
return dom.getStringValueX(node); |
|
132 |
} |
|
133 |
||
134 |
/** |
|
135 |
* XSLT Standard function string(value) |
|
136 |
*/ |
|
137 |
public static String stringF(Object obj, DOM dom) { |
|
138 |
if (obj instanceof DTMAxisIterator) { |
|
139 |
return dom.getStringValueX(((DTMAxisIterator)obj).reset().next()); |
|
140 |
} |
|
141 |
else if (obj instanceof Node) { |
|
142 |
return dom.getStringValueX(((Node)obj).node); |
|
143 |
} |
|
144 |
else if (obj instanceof DOM) { |
|
145 |
return ((DOM)obj).getStringValue(); |
|
146 |
} |
|
147 |
else { |
|
148 |
return obj.toString(); |
|
149 |
} |
|
150 |
} |
|
151 |
||
152 |
/** |
|
153 |
* XSLT Standard function string(value) |
|
154 |
*/ |
|
155 |
public static String stringF(Object obj, int node, DOM dom) { |
|
156 |
if (obj instanceof DTMAxisIterator) { |
|
157 |
return dom.getStringValueX(((DTMAxisIterator)obj).reset().next()); |
|
158 |
} |
|
159 |
else if (obj instanceof Node) { |
|
160 |
return dom.getStringValueX(((Node)obj).node); |
|
161 |
} |
|
162 |
else if (obj instanceof DOM) { |
|
12458 | 163 |
// When the first argument is a DOM we want the whole |
12005 | 164 |
// DOM and not just a single node - that would not make sense. |
165 |
//return ((DOM)obj).getStringValueX(node); |
|
166 |
return ((DOM)obj).getStringValue(); |
|
167 |
} |
|
168 |
else if (obj instanceof Double) { |
|
169 |
Double d = (Double)obj; |
|
170 |
final String result = d.toString(); |
|
171 |
final int length = result.length(); |
|
172 |
if ((result.charAt(length-2)=='.') && |
|
173 |
(result.charAt(length-1) == '0')) |
|
174 |
return result.substring(0, length-2); |
|
175 |
else |
|
176 |
return result; |
|
177 |
} |
|
178 |
else { |
|
179 |
return obj != null ? obj.toString() : ""; |
|
180 |
} |
|
181 |
} |
|
182 |
||
183 |
/** |
|
184 |
* XSLT Standard function number() |
|
185 |
*/ |
|
186 |
public static double numberF(int node, DOM dom) { |
|
187 |
return stringToReal(dom.getStringValueX(node)); |
|
188 |
} |
|
189 |
||
190 |
/** |
|
191 |
* XSLT Standard function number(value) |
|
192 |
*/ |
|
193 |
public static double numberF(Object obj, DOM dom) { |
|
194 |
if (obj instanceof Double) { |
|
195 |
return ((Double) obj).doubleValue(); |
|
196 |
} |
|
197 |
else if (obj instanceof Integer) { |
|
198 |
return ((Integer) obj).doubleValue(); |
|
199 |
} |
|
200 |
else if (obj instanceof Boolean) { |
|
201 |
return ((Boolean) obj).booleanValue() ? 1.0 : 0.0; |
|
202 |
} |
|
203 |
else if (obj instanceof String) { |
|
204 |
return stringToReal((String) obj); |
|
205 |
} |
|
206 |
else if (obj instanceof DTMAxisIterator) { |
|
207 |
DTMAxisIterator iter = (DTMAxisIterator) obj; |
|
208 |
return stringToReal(dom.getStringValueX(iter.reset().next())); |
|
209 |
} |
|
210 |
else if (obj instanceof Node) { |
|
211 |
return stringToReal(dom.getStringValueX(((Node) obj).node)); |
|
212 |
} |
|
213 |
else if (obj instanceof DOM) { |
|
214 |
return stringToReal(((DOM) obj).getStringValue()); |
|
215 |
} |
|
216 |
else { |
|
217 |
final String className = obj.getClass().getName(); |
|
218 |
runTimeError(INVALID_ARGUMENT_ERR, className, "number()"); |
|
219 |
return 0.0; |
|
220 |
} |
|
221 |
} |
|
222 |
||
223 |
/** |
|
224 |
* XSLT Standard function round() |
|
225 |
*/ |
|
226 |
public static double roundF(double d) { |
|
227 |
return (d<-0.5 || d>0.0)?Math.floor(d+0.5):((d==0.0)? |
|
228 |
d:(Double.isNaN(d)?Double.NaN:-0.0)); |
|
229 |
} |
|
230 |
||
231 |
/** |
|
232 |
* XSLT Standard function boolean() |
|
233 |
*/ |
|
234 |
public static boolean booleanF(Object obj) { |
|
235 |
if (obj instanceof Double) { |
|
236 |
final double temp = ((Double) obj).doubleValue(); |
|
237 |
return temp != 0.0 && !Double.isNaN(temp); |
|
238 |
} |
|
239 |
else if (obj instanceof Integer) { |
|
240 |
return ((Integer) obj).doubleValue() != 0; |
|
241 |
} |
|
242 |
else if (obj instanceof Boolean) { |
|
243 |
return ((Boolean) obj).booleanValue(); |
|
244 |
} |
|
245 |
else if (obj instanceof String) { |
|
246 |
return !((String) obj).equals(EMPTYSTRING); |
|
247 |
} |
|
248 |
else if (obj instanceof DTMAxisIterator) { |
|
249 |
DTMAxisIterator iter = (DTMAxisIterator) obj; |
|
250 |
return iter.reset().next() != DTMAxisIterator.END; |
|
251 |
} |
|
252 |
else if (obj instanceof Node) { |
|
253 |
return true; |
|
254 |
} |
|
255 |
else if (obj instanceof DOM) { |
|
256 |
String temp = ((DOM) obj).getStringValue(); |
|
257 |
return !temp.equals(EMPTYSTRING); |
|
258 |
} |
|
259 |
else { |
|
260 |
final String className = obj.getClass().getName(); |
|
261 |
runTimeError(INVALID_ARGUMENT_ERR, className, "boolean()"); |
|
262 |
} |
|
263 |
return false; |
|
264 |
} |
|
265 |
||
266 |
/** |
|
267 |
* XSLT Standard function substring(). Must take a double because of |
|
268 |
* conversions resulting into NaNs and rounding. |
|
269 |
*/ |
|
270 |
public static String substringF(String value, double start) { |
|
271 |
if (Double.isNaN(start)) |
|
272 |
return(EMPTYSTRING); |
|
273 |
||
29763
e69895779fa3
8074297: substring in XSLT returns wrong character if string contains supplementary chars
aefimov
parents:
28694
diff
changeset
|
274 |
final int strlen = getStringLength(value); |
28694
b99e1eee0669
8062923: XSL: Run-time internal error in 'substring()'
aefimov
parents:
25868
diff
changeset
|
275 |
int istart = (int)Math.round(start) - 1; |
12005 | 276 |
|
277 |
if (istart > strlen) |
|
278 |
return(EMPTYSTRING); |
|
279 |
if (istart < 1) |
|
280 |
istart = 0; |
|
281 |
try { |
|
29763
e69895779fa3
8074297: substring in XSLT returns wrong character if string contains supplementary chars
aefimov
parents:
28694
diff
changeset
|
282 |
istart = value.offsetByCodePoints(0, istart); |
12005 | 283 |
return value.substring(istart); |
284 |
} catch (IndexOutOfBoundsException e) { |
|
285 |
runTimeError(RUN_TIME_INTERNAL_ERR, "substring()"); |
|
286 |
return null; |
|
287 |
} |
|
288 |
} |
|
289 |
||
290 |
/** |
|
291 |
* XSLT Standard function substring(). Must take a double because of |
|
292 |
* conversions resulting into NaNs and rounding. |
|
293 |
*/ |
|
294 |
public static String substringF(String value, double start, double length) { |
|
295 |
if (Double.isInfinite(start) || |
|
296 |
Double.isNaN(start) || |
|
28694
b99e1eee0669
8062923: XSL: Run-time internal error in 'substring()'
aefimov
parents:
25868
diff
changeset
|
297 |
Double.isNaN(length) || |
b99e1eee0669
8062923: XSL: Run-time internal error in 'substring()'
aefimov
parents:
25868
diff
changeset
|
298 |
length < 0) |
12005 | 299 |
return(EMPTYSTRING); |
300 |
||
28694
b99e1eee0669
8062923: XSL: Run-time internal error in 'substring()'
aefimov
parents:
25868
diff
changeset
|
301 |
int istart = (int)Math.round(start) - 1; |
29764
63210c2facec
8076290: JCK test api/xsl/conf/string/string17 starts failing after JDK-8074297
aefimov
parents:
29763
diff
changeset
|
302 |
int ilength = (int)Math.round(length); |
12005 | 303 |
final int isum; |
304 |
if (Double.isInfinite(length)) |
|
305 |
isum = Integer.MAX_VALUE; |
|
306 |
else |
|
29763
e69895779fa3
8074297: substring in XSLT returns wrong character if string contains supplementary chars
aefimov
parents:
28694
diff
changeset
|
307 |
isum = istart + ilength; |
12005 | 308 |
|
29763
e69895779fa3
8074297: substring in XSLT returns wrong character if string contains supplementary chars
aefimov
parents:
28694
diff
changeset
|
309 |
final int strlen = getStringLength(value); |
12005 | 310 |
if (isum < 0 || istart > strlen) |
311 |
return(EMPTYSTRING); |
|
312 |
||
29764
63210c2facec
8076290: JCK test api/xsl/conf/string/string17 starts failing after JDK-8074297
aefimov
parents:
29763
diff
changeset
|
313 |
if (istart < 0) { |
63210c2facec
8076290: JCK test api/xsl/conf/string/string17 starts failing after JDK-8074297
aefimov
parents:
29763
diff
changeset
|
314 |
ilength += istart; |
12005 | 315 |
istart = 0; |
29764
63210c2facec
8076290: JCK test api/xsl/conf/string/string17 starts failing after JDK-8074297
aefimov
parents:
29763
diff
changeset
|
316 |
} |
12005 | 317 |
|
318 |
try { |
|
29763
e69895779fa3
8074297: substring in XSLT returns wrong character if string contains supplementary chars
aefimov
parents:
28694
diff
changeset
|
319 |
istart = value.offsetByCodePoints(0, istart); |
e69895779fa3
8074297: substring in XSLT returns wrong character if string contains supplementary chars
aefimov
parents:
28694
diff
changeset
|
320 |
if (isum > strlen) { |
12005 | 321 |
return value.substring(istart); |
29763
e69895779fa3
8074297: substring in XSLT returns wrong character if string contains supplementary chars
aefimov
parents:
28694
diff
changeset
|
322 |
} else { |
e69895779fa3
8074297: substring in XSLT returns wrong character if string contains supplementary chars
aefimov
parents:
28694
diff
changeset
|
323 |
int offset = value.offsetByCodePoints(istart, ilength); |
e69895779fa3
8074297: substring in XSLT returns wrong character if string contains supplementary chars
aefimov
parents:
28694
diff
changeset
|
324 |
return value.substring(istart, offset); |
e69895779fa3
8074297: substring in XSLT returns wrong character if string contains supplementary chars
aefimov
parents:
28694
diff
changeset
|
325 |
} |
12005 | 326 |
} catch (IndexOutOfBoundsException e) { |
327 |
runTimeError(RUN_TIME_INTERNAL_ERR, "substring()"); |
|
328 |
return null; |
|
329 |
} |
|
330 |
} |
|
331 |
||
332 |
/** |
|
333 |
* XSLT Standard function substring-after(). |
|
334 |
*/ |
|
335 |
public static String substring_afterF(String value, String substring) { |
|
336 |
final int index = value.indexOf(substring); |
|
337 |
if (index >= 0) |
|
338 |
return value.substring(index + substring.length()); |
|
339 |
else |
|
340 |
return EMPTYSTRING; |
|
341 |
} |
|
342 |
||
343 |
/** |
|
344 |
* XSLT Standard function substring-before(). |
|
345 |
*/ |
|
346 |
public static String substring_beforeF(String value, String substring) { |
|
347 |
final int index = value.indexOf(substring); |
|
348 |
if (index >= 0) |
|
349 |
return value.substring(0, index); |
|
350 |
else |
|
351 |
return EMPTYSTRING; |
|
352 |
} |
|
353 |
||
354 |
/** |
|
355 |
* XSLT Standard function translate(). |
|
356 |
*/ |
|
357 |
public static String translateF(String value, String from, String to) { |
|
358 |
final int tol = to.length(); |
|
359 |
final int froml = from.length(); |
|
360 |
final int valuel = value.length(); |
|
361 |
||
362 |
final StringBuilder result = threadLocalStringBuilder.get(); |
|
363 |
result.setLength(0); |
|
364 |
for (int j, i = 0; i < valuel; i++) { |
|
365 |
final char ch = value.charAt(i); |
|
366 |
for (j = 0; j < froml; j++) { |
|
367 |
if (ch == from.charAt(j)) { |
|
368 |
if (j < tol) |
|
369 |
result.append(to.charAt(j)); |
|
370 |
break; |
|
371 |
} |
|
372 |
} |
|
373 |
if (j == froml) |
|
374 |
result.append(ch); |
|
375 |
} |
|
376 |
return result.toString(); |
|
377 |
} |
|
378 |
||
379 |
/** |
|
380 |
* XSLT Standard function normalize-space(). |
|
381 |
*/ |
|
382 |
public static String normalize_spaceF(int node, DOM dom) { |
|
383 |
return normalize_spaceF(dom.getStringValueX(node)); |
|
384 |
} |
|
385 |
||
386 |
/** |
|
387 |
* XSLT Standard function normalize-space(string). |
|
388 |
*/ |
|
389 |
public static String normalize_spaceF(String value) { |
|
390 |
int i = 0, n = value.length(); |
|
391 |
StringBuilder result = threadLocalStringBuilder.get(); |
|
392 |
result.setLength(0); |
|
393 |
||
394 |
while (i < n && isWhiteSpace(value.charAt(i))) |
|
395 |
i++; |
|
396 |
||
397 |
while (true) { |
|
398 |
while (i < n && !isWhiteSpace(value.charAt(i))) { |
|
399 |
result.append(value.charAt(i++)); |
|
400 |
} |
|
401 |
if (i == n) |
|
402 |
break; |
|
403 |
while (i < n && isWhiteSpace(value.charAt(i))) { |
|
404 |
i++; |
|
405 |
} |
|
406 |
if (i < n) |
|
407 |
result.append(' '); |
|
408 |
} |
|
409 |
return result.toString(); |
|
410 |
} |
|
411 |
||
412 |
/** |
|
413 |
* XSLT Standard function generate-id(). |
|
414 |
*/ |
|
415 |
public static String generate_idF(int node) { |
|
416 |
if (node > 0) |
|
417 |
// Only generate ID if node exists |
|
418 |
return "N" + node; |
|
419 |
else |
|
420 |
// Otherwise return an empty string |
|
421 |
return EMPTYSTRING; |
|
422 |
} |
|
423 |
||
424 |
/** |
|
425 |
* utility function for calls to local-name(). |
|
426 |
*/ |
|
427 |
public static String getLocalName(String value) { |
|
428 |
int idx = value.lastIndexOf(':'); |
|
429 |
if (idx >= 0) value = value.substring(idx + 1); |
|
430 |
idx = value.lastIndexOf('@'); |
|
431 |
if (idx >= 0) value = value.substring(idx + 1); |
|
432 |
return(value); |
|
433 |
} |
|
434 |
||
435 |
/** |
|
436 |
* External functions that cannot be resolved are replaced with a call |
|
437 |
* to this method. This method will generate a runtime errors. A good |
|
438 |
* stylesheet checks whether the function exists using conditional |
|
439 |
* constructs, and never really tries to call it if it doesn't exist. |
|
440 |
* But simple stylesheets may result in a call to this method. |
|
441 |
* The compiler should generate a warning if it encounters a call to |
|
442 |
* an unresolved external function. |
|
443 |
*/ |
|
444 |
public static void unresolved_externalF(String name) { |
|
445 |
runTimeError(EXTERNAL_FUNC_ERR, name); |
|
446 |
} |
|
447 |
||
448 |
/** |
|
449 |
* Utility function to throw a runtime error on the use of an extension |
|
450 |
* function when the secure processing feature is set to true. |
|
451 |
*/ |
|
452 |
public static void unallowed_extension_functionF(String name) { |
|
453 |
runTimeError(UNALLOWED_EXTENSION_FUNCTION_ERR, name); |
|
454 |
} |
|
455 |
||
456 |
/** |
|
457 |
* Utility function to throw a runtime error on the use of an extension |
|
458 |
* element when the secure processing feature is set to true. |
|
459 |
*/ |
|
460 |
public static void unallowed_extension_elementF(String name) { |
|
461 |
runTimeError(UNALLOWED_EXTENSION_ELEMENT_ERR, name); |
|
462 |
} |
|
463 |
||
464 |
/** |
|
465 |
* Utility function to throw a runtime error for an unsupported element. |
|
466 |
* |
|
467 |
* This is only used in forward-compatibility mode, when the control flow |
|
468 |
* cannot be determined. In 1.0 mode, the error message is emitted at |
|
469 |
* compile time. |
|
470 |
*/ |
|
471 |
public static void unsupported_ElementF(String qname, boolean isExtension) { |
|
472 |
if (isExtension) |
|
473 |
runTimeError(UNSUPPORTED_EXT_ERR, qname); |
|
474 |
else |
|
475 |
runTimeError(UNSUPPORTED_XSL_ERR, qname); |
|
476 |
} |
|
477 |
||
478 |
/** |
|
479 |
* XSLT Standard function namespace-uri(node-set). |
|
480 |
*/ |
|
481 |
public static String namespace_uriF(DTMAxisIterator iter, DOM dom) { |
|
482 |
return namespace_uriF(iter.next(), dom); |
|
483 |
} |
|
484 |
||
485 |
/** |
|
486 |
* XSLT Standard function system-property(name) |
|
487 |
*/ |
|
488 |
public static String system_propertyF(String name) { |
|
489 |
if (name.equals("xsl:version")) |
|
490 |
return("1.0"); |
|
491 |
if (name.equals("xsl:vendor")) |
|
492 |
return("Apache Software Foundation (Xalan XSLTC)"); |
|
493 |
if (name.equals("xsl:vendor-url")) |
|
494 |
return("http://xml.apache.org/xalan-j"); |
|
495 |
||
496 |
runTimeError(INVALID_ARGUMENT_ERR, name, "system-property()"); |
|
497 |
return(EMPTYSTRING); |
|
498 |
} |
|
499 |
||
500 |
/** |
|
501 |
* XSLT Standard function namespace-uri(). |
|
502 |
*/ |
|
503 |
public static String namespace_uriF(int node, DOM dom) { |
|
504 |
final String value = dom.getNodeName(node); |
|
505 |
final int colon = value.lastIndexOf(':'); |
|
506 |
if (colon >= 0) |
|
507 |
return value.substring(0, colon); |
|
508 |
else |
|
509 |
return EMPTYSTRING; |
|
510 |
} |
|
511 |
||
512 |
/** |
|
513 |
* Implements the object-type() extension function. |
|
514 |
* |
|
515 |
* @see <a href="http://www.exslt.org/">EXSLT</a> |
|
516 |
*/ |
|
517 |
public static String objectTypeF(Object obj) |
|
518 |
{ |
|
519 |
if (obj instanceof String) |
|
520 |
return "string"; |
|
521 |
else if (obj instanceof Boolean) |
|
522 |
return "boolean"; |
|
523 |
else if (obj instanceof Number) |
|
524 |
return "number"; |
|
525 |
else if (obj instanceof DOM) |
|
526 |
return "RTF"; |
|
527 |
else if (obj instanceof DTMAxisIterator) |
|
528 |
return "node-set"; |
|
529 |
else |
|
530 |
return "unknown"; |
|
531 |
} |
|
532 |
||
533 |
/** |
|
534 |
* Implements the nodeset() extension function. |
|
535 |
*/ |
|
536 |
public static DTMAxisIterator nodesetF(Object obj) { |
|
537 |
if (obj instanceof DOM) { |
|
538 |
//final DOMAdapter adapter = (DOMAdapter) obj; |
|
539 |
final DOM dom = (DOM)obj; |
|
540 |
return new SingletonIterator(dom.getDocument(), true); |
|
541 |
} |
|
542 |
else if (obj instanceof DTMAxisIterator) { |
|
543 |
return (DTMAxisIterator) obj; |
|
544 |
} |
|
545 |
else { |
|
546 |
final String className = obj.getClass().getName(); |
|
547 |
runTimeError(DATA_CONVERSION_ERR, "node-set", className); |
|
548 |
return null; |
|
549 |
} |
|
550 |
} |
|
551 |
||
552 |
//-- Begin utility functions |
|
553 |
||
554 |
private static boolean isWhiteSpace(char ch) { |
|
555 |
return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'; |
|
556 |
} |
|
557 |
||
558 |
private static boolean compareStrings(String lstring, String rstring, |
|
559 |
int op, DOM dom) { |
|
560 |
switch (op) { |
|
561 |
case Operators.EQ: |
|
562 |
return lstring.equals(rstring); |
|
563 |
||
564 |
case Operators.NE: |
|
565 |
return !lstring.equals(rstring); |
|
566 |
||
567 |
case Operators.GT: |
|
568 |
return numberF(lstring, dom) > numberF(rstring, dom); |
|
569 |
||
570 |
case Operators.LT: |
|
571 |
return numberF(lstring, dom) < numberF(rstring, dom); |
|
572 |
||
573 |
case Operators.GE: |
|
574 |
return numberF(lstring, dom) >= numberF(rstring, dom); |
|
575 |
||
576 |
case Operators.LE: |
|
577 |
return numberF(lstring, dom) <= numberF(rstring, dom); |
|
578 |
||
579 |
default: |
|
580 |
runTimeError(RUN_TIME_INTERNAL_ERR, "compare()"); |
|
581 |
return false; |
|
582 |
} |
|
583 |
} |
|
584 |
||
585 |
/** |
|
586 |
* Utility function: node-set/node-set compare. |
|
587 |
*/ |
|
588 |
public static boolean compare(DTMAxisIterator left, DTMAxisIterator right, |
|
589 |
int op, DOM dom) { |
|
590 |
int lnode; |
|
591 |
left.reset(); |
|
592 |
||
593 |
while ((lnode = left.next()) != DTMAxisIterator.END) { |
|
594 |
final String lvalue = dom.getStringValueX(lnode); |
|
595 |
||
596 |
int rnode; |
|
597 |
right.reset(); |
|
598 |
while ((rnode = right.next()) != DTMAxisIterator.END) { |
|
599 |
// String value must be the same if both nodes are the same |
|
600 |
if (lnode == rnode) { |
|
601 |
if (op == Operators.EQ) { |
|
602 |
return true; |
|
603 |
} else if (op == Operators.NE) { |
|
604 |
continue; |
|
605 |
} |
|
606 |
} |
|
607 |
if (compareStrings(lvalue, dom.getStringValueX(rnode), op, |
|
608 |
dom)) { |
|
609 |
return true; |
|
610 |
} |
|
611 |
} |
|
612 |
} |
|
613 |
return false; |
|
614 |
} |
|
615 |
||
616 |
public static boolean compare(int node, DTMAxisIterator iterator, |
|
617 |
int op, DOM dom) { |
|
618 |
//iterator.reset(); |
|
619 |
||
620 |
int rnode; |
|
621 |
String value; |
|
622 |
||
623 |
switch(op) { |
|
624 |
case Operators.EQ: |
|
625 |
rnode = iterator.next(); |
|
626 |
if (rnode != DTMAxisIterator.END) { |
|
627 |
value = dom.getStringValueX(node); |
|
628 |
do { |
|
629 |
if (node == rnode |
|
630 |
|| value.equals(dom.getStringValueX(rnode))) { |
|
631 |
return true; |
|
632 |
} |
|
633 |
} while ((rnode = iterator.next()) != DTMAxisIterator.END); |
|
634 |
} |
|
635 |
break; |
|
636 |
case Operators.NE: |
|
637 |
rnode = iterator.next(); |
|
638 |
if (rnode != DTMAxisIterator.END) { |
|
639 |
value = dom.getStringValueX(node); |
|
640 |
do { |
|
641 |
if (node != rnode |
|
642 |
&& !value.equals(dom.getStringValueX(rnode))) { |
|
643 |
return true; |
|
644 |
} |
|
645 |
} while ((rnode = iterator.next()) != DTMAxisIterator.END); |
|
646 |
} |
|
647 |
break; |
|
648 |
case Operators.LT: |
|
649 |
// Assume we're comparing document order here |
|
650 |
while ((rnode = iterator.next()) != DTMAxisIterator.END) { |
|
651 |
if (rnode > node) return true; |
|
652 |
} |
|
653 |
break; |
|
654 |
case Operators.GT: |
|
655 |
// Assume we're comparing document order here |
|
656 |
while ((rnode = iterator.next()) != DTMAxisIterator.END) { |
|
657 |
if (rnode < node) return true; |
|
658 |
} |
|
659 |
break; |
|
660 |
} |
|
661 |
return(false); |
|
662 |
} |
|
663 |
||
664 |
/** |
|
665 |
* Utility function: node-set/number compare. |
|
666 |
*/ |
|
667 |
public static boolean compare(DTMAxisIterator left, final double rnumber, |
|
668 |
final int op, DOM dom) { |
|
669 |
int node; |
|
670 |
//left.reset(); |
|
671 |
||
672 |
switch (op) { |
|
673 |
case Operators.EQ: |
|
674 |
while ((node = left.next()) != DTMAxisIterator.END) { |
|
675 |
if (numberF(dom.getStringValueX(node), dom) == rnumber) |
|
676 |
return true; |
|
677 |
} |
|
678 |
break; |
|
679 |
||
680 |
case Operators.NE: |
|
681 |
while ((node = left.next()) != DTMAxisIterator.END) { |
|
682 |
if (numberF(dom.getStringValueX(node), dom) != rnumber) |
|
683 |
return true; |
|
684 |
} |
|
685 |
break; |
|
686 |
||
687 |
case Operators.GT: |
|
688 |
while ((node = left.next()) != DTMAxisIterator.END) { |
|
689 |
if (numberF(dom.getStringValueX(node), dom) > rnumber) |
|
690 |
return true; |
|
691 |
} |
|
692 |
break; |
|
693 |
||
694 |
case Operators.LT: |
|
695 |
while ((node = left.next()) != DTMAxisIterator.END) { |
|
696 |
if (numberF(dom.getStringValueX(node), dom) < rnumber) |
|
697 |
return true; |
|
698 |
} |
|
699 |
break; |
|
700 |
||
701 |
case Operators.GE: |
|
702 |
while ((node = left.next()) != DTMAxisIterator.END) { |
|
703 |
if (numberF(dom.getStringValueX(node), dom) >= rnumber) |
|
704 |
return true; |
|
705 |
} |
|
706 |
break; |
|
707 |
||
708 |
case Operators.LE: |
|
709 |
while ((node = left.next()) != DTMAxisIterator.END) { |
|
710 |
if (numberF(dom.getStringValueX(node), dom) <= rnumber) |
|
711 |
return true; |
|
712 |
} |
|
713 |
break; |
|
714 |
||
715 |
default: |
|
716 |
runTimeError(RUN_TIME_INTERNAL_ERR, "compare()"); |
|
717 |
} |
|
718 |
||
719 |
return false; |
|
720 |
} |
|
721 |
||
722 |
/** |
|
723 |
* Utility function: node-set/string comparison. |
|
724 |
*/ |
|
725 |
public static boolean compare(DTMAxisIterator left, final String rstring, |
|
726 |
int op, DOM dom) { |
|
727 |
int node; |
|
728 |
//left.reset(); |
|
729 |
while ((node = left.next()) != DTMAxisIterator.END) { |
|
730 |
if (compareStrings(dom.getStringValueX(node), rstring, op, dom)) { |
|
731 |
return true; |
|
732 |
} |
|
733 |
} |
|
734 |
return false; |
|
735 |
} |
|
736 |
||
737 |
||
738 |
public static boolean compare(Object left, Object right, |
|
739 |
int op, DOM dom) |
|
740 |
{ |
|
741 |
boolean result = false; |
|
742 |
boolean hasSimpleArgs = hasSimpleType(left) && hasSimpleType(right); |
|
743 |
||
744 |
if (op != Operators.EQ && op != Operators.NE) { |
|
745 |
// If node-boolean comparison -> convert node to boolean |
|
746 |
if (left instanceof Node || right instanceof Node) { |
|
747 |
if (left instanceof Boolean) { |
|
45853
bfa06be36a17
8181154: Fix lint warnings in JAXP repo: deprecation
joehw
parents:
45490
diff
changeset
|
748 |
right = booleanF(right); |
12005 | 749 |
hasSimpleArgs = true; |
750 |
} |
|
751 |
if (right instanceof Boolean) { |
|
45853
bfa06be36a17
8181154: Fix lint warnings in JAXP repo: deprecation
joehw
parents:
45490
diff
changeset
|
752 |
left = booleanF(left); |
12005 | 753 |
hasSimpleArgs = true; |
754 |
} |
|
755 |
} |
|
756 |
||
757 |
if (hasSimpleArgs) { |
|
758 |
switch (op) { |
|
759 |
case Operators.GT: |
|
760 |
return numberF(left, dom) > numberF(right, dom); |
|
761 |
||
762 |
case Operators.LT: |
|
763 |
return numberF(left, dom) < numberF(right, dom); |
|
764 |
||
765 |
case Operators.GE: |
|
766 |
return numberF(left, dom) >= numberF(right, dom); |
|
767 |
||
768 |
case Operators.LE: |
|
769 |
return numberF(left, dom) <= numberF(right, dom); |
|
770 |
||
771 |
default: |
|
772 |
runTimeError(RUN_TIME_INTERNAL_ERR, "compare()"); |
|
773 |
} |
|
774 |
} |
|
775 |
// falls through |
|
776 |
} |
|
777 |
||
778 |
if (hasSimpleArgs) { |
|
779 |
if (left instanceof Boolean || right instanceof Boolean) { |
|
780 |
result = booleanF(left) == booleanF(right); |
|
781 |
} |
|
782 |
else if (left instanceof Double || right instanceof Double || |
|
783 |
left instanceof Integer || right instanceof Integer) { |
|
784 |
result = numberF(left, dom) == numberF(right, dom); |
|
785 |
} |
|
786 |
else { // compare them as strings |
|
787 |
result = stringF(left, dom).equals(stringF(right, dom)); |
|
788 |
} |
|
789 |
||
790 |
if (op == Operators.NE) { |
|
791 |
result = !result; |
|
792 |
} |
|
793 |
} |
|
794 |
else { |
|
795 |
if (left instanceof Node) { |
|
796 |
left = new SingletonIterator(((Node)left).node); |
|
797 |
} |
|
798 |
if (right instanceof Node) { |
|
799 |
right = new SingletonIterator(((Node)right).node); |
|
800 |
} |
|
801 |
||
802 |
if (hasSimpleType(left) || |
|
803 |
left instanceof DOM && right instanceof DTMAxisIterator) { |
|
804 |
// swap operands and operator |
|
805 |
final Object temp = right; right = left; left = temp; |
|
806 |
op = Operators.swapOp(op); |
|
807 |
} |
|
808 |
||
809 |
if (left instanceof DOM) { |
|
810 |
if (right instanceof Boolean) { |
|
811 |
result = ((Boolean)right).booleanValue(); |
|
812 |
return result == (op == Operators.EQ); |
|
813 |
} |
|
814 |
||
815 |
final String sleft = ((DOM)left).getStringValue(); |
|
816 |
||
817 |
if (right instanceof Number) { |
|
818 |
result = ((Number)right).doubleValue() == |
|
819 |
stringToReal(sleft); |
|
820 |
} |
|
821 |
else if (right instanceof String) { |
|
822 |
result = sleft.equals((String)right); |
|
823 |
} |
|
824 |
else if (right instanceof DOM) { |
|
825 |
result = sleft.equals(((DOM)right).getStringValue()); |
|
826 |
} |
|
827 |
||
828 |
if (op == Operators.NE) { |
|
829 |
result = !result; |
|
830 |
} |
|
831 |
return result; |
|
832 |
} |
|
833 |
||
834 |
// Next, node-set/t for t in {real, string, node-set, result-tree} |
|
835 |
||
836 |
DTMAxisIterator iter = ((DTMAxisIterator)left).reset(); |
|
837 |
||
838 |
if (right instanceof DTMAxisIterator) { |
|
839 |
result = compare(iter, (DTMAxisIterator)right, op, dom); |
|
840 |
} |
|
841 |
else if (right instanceof String) { |
|
842 |
result = compare(iter, (String)right, op, dom); |
|
843 |
} |
|
844 |
else if (right instanceof Number) { |
|
845 |
final double temp = ((Number)right).doubleValue(); |
|
846 |
result = compare(iter, temp, op, dom); |
|
847 |
} |
|
848 |
else if (right instanceof Boolean) { |
|
849 |
boolean temp = ((Boolean)right).booleanValue(); |
|
850 |
result = (iter.reset().next() != DTMAxisIterator.END) == temp; |
|
851 |
} |
|
852 |
else if (right instanceof DOM) { |
|
853 |
result = compare(iter, ((DOM)right).getStringValue(), |
|
854 |
op, dom); |
|
855 |
} |
|
856 |
else if (right == null) { |
|
857 |
return(false); |
|
858 |
} |
|
859 |
else { |
|
860 |
final String className = right.getClass().getName(); |
|
861 |
runTimeError(INVALID_ARGUMENT_ERR, className, "compare()"); |
|
862 |
} |
|
863 |
} |
|
864 |
return result; |
|
865 |
} |
|
866 |
||
867 |
/** |
|
868 |
* Utility function: used to test context node's language |
|
869 |
*/ |
|
870 |
public static boolean testLanguage(String testLang, DOM dom, int node) { |
|
871 |
// language for context node (if any) |
|
872 |
String nodeLang = dom.getLanguage(node); |
|
873 |
if (nodeLang == null) |
|
874 |
return(false); |
|
875 |
else |
|
876 |
nodeLang = nodeLang.toLowerCase(); |
|
877 |
||
878 |
// compare context node's language agains test language |
|
879 |
testLang = testLang.toLowerCase(); |
|
880 |
if (testLang.length() == 2) { |
|
881 |
return(nodeLang.startsWith(testLang)); |
|
882 |
} |
|
883 |
else { |
|
884 |
return(nodeLang.equals(testLang)); |
|
885 |
} |
|
886 |
} |
|
887 |
||
888 |
private static boolean hasSimpleType(Object obj) { |
|
889 |
return obj instanceof Boolean || obj instanceof Double || |
|
890 |
obj instanceof Integer || obj instanceof String || |
|
891 |
obj instanceof Node || obj instanceof DOM; |
|
892 |
} |
|
893 |
||
894 |
/** |
|
895 |
* Utility function: used in StringType to convert a string to a real. |
|
896 |
*/ |
|
897 |
public static double stringToReal(String s) { |
|
898 |
try { |
|
899 |
return Double.valueOf(s).doubleValue(); |
|
900 |
} |
|
901 |
catch (NumberFormatException e) { |
|
902 |
return Double.NaN; |
|
903 |
} |
|
904 |
} |
|
905 |
||
906 |
/** |
|
907 |
* Utility function: used in StringType to convert a string to an int. |
|
908 |
*/ |
|
909 |
public static int stringToInt(String s) { |
|
910 |
try { |
|
911 |
return Integer.parseInt(s); |
|
912 |
} |
|
913 |
catch (NumberFormatException e) { |
|
914 |
return(-1); // ??? |
|
915 |
} |
|
916 |
} |
|
917 |
||
918 |
private static final int DOUBLE_FRACTION_DIGITS = 340; |
|
919 |
private static final double lowerBounds = 0.001; |
|
920 |
private static final double upperBounds = 10000000; |
|
921 |
private static DecimalFormat defaultFormatter, xpathFormatter; |
|
922 |
private static String defaultPattern = ""; |
|
923 |
||
924 |
static { |
|
925 |
NumberFormat f = NumberFormat.getInstance(Locale.getDefault()); |
|
926 |
defaultFormatter = (f instanceof DecimalFormat) ? |
|
927 |
(DecimalFormat) f : new DecimalFormat(); |
|
928 |
// Set max fraction digits so that truncation does not occur. Setting |
|
929 |
// the max to Integer.MAX_VALUE may cause problems with some JDK's. |
|
930 |
defaultFormatter.setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS); |
|
931 |
defaultFormatter.setMinimumFractionDigits(0); |
|
932 |
defaultFormatter.setMinimumIntegerDigits(1); |
|
933 |
defaultFormatter.setGroupingUsed(false); |
|
934 |
||
935 |
// This formatter is used to convert numbers according to the XPath |
|
936 |
// 1.0 syntax which ignores locales (http://www.w3.org/TR/xpath#NT-Number) |
|
937 |
xpathFormatter = new DecimalFormat("", |
|
938 |
new DecimalFormatSymbols(Locale.US)); |
|
939 |
xpathFormatter.setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS); |
|
940 |
xpathFormatter.setMinimumFractionDigits(0); |
|
941 |
xpathFormatter.setMinimumIntegerDigits(1); |
|
942 |
xpathFormatter.setGroupingUsed(false); |
|
943 |
} |
|
944 |
||
945 |
/** |
|
946 |
* Utility function: used in RealType to convert a real to a string. |
|
947 |
* Removes the decimal if null. Uses a specialized formatter object |
|
948 |
* for very large and very small numbers that ignores locales, thus |
|
949 |
* using always using "." as a decimal separator. |
|
950 |
*/ |
|
951 |
public static String realToString(double d) { |
|
952 |
final double m = Math.abs(d); |
|
953 |
if ((m >= lowerBounds) && (m < upperBounds)) { |
|
954 |
final String result = Double.toString(d); |
|
955 |
final int length = result.length(); |
|
956 |
// Remove leading zeros. |
|
957 |
if ((result.charAt(length-2) == '.') && |
|
958 |
(result.charAt(length-1) == '0')) |
|
959 |
return result.substring(0, length-2); |
|
960 |
else |
|
961 |
return result; |
|
962 |
} |
|
963 |
else { |
|
18356 | 964 |
if (Double.isNaN(d) || Double.isInfinite(d)) |
12005 | 965 |
return(Double.toString(d)); |
966 |
||
18355
381a149016f9
8015978: Incorrect transformation of XPath expression "string(-0)"
coffeys
parents:
16953
diff
changeset
|
967 |
//Convert -0.0 to +0.0 other values remains the same |
381a149016f9
8015978: Incorrect transformation of XPath expression "string(-0)"
coffeys
parents:
16953
diff
changeset
|
968 |
d = d + 0.0; |
381a149016f9
8015978: Incorrect transformation of XPath expression "string(-0)"
coffeys
parents:
16953
diff
changeset
|
969 |
|
12005 | 970 |
// Use the XPath formatter to ignore locales |
971 |
StringBuffer result = threadLocalStringBuffer.get(); |
|
972 |
result.setLength(0); |
|
973 |
xpathFormatter.format(d, result, _fieldPosition); |
|
974 |
return result.toString(); |
|
975 |
} |
|
976 |
} |
|
977 |
||
978 |
/** |
|
979 |
* Utility function: used in RealType to convert a real to an integer |
|
980 |
*/ |
|
981 |
public static int realToInt(double d) { |
|
982 |
return (int)d; |
|
983 |
} |
|
984 |
||
985 |
/** |
|
986 |
* Utility function: used to format/adjust a double to a string. The |
|
33349 | 987 |
* DecimalFormat object comes from the 'formatSymbols' map in |
12005 | 988 |
* AbstractTranslet. |
989 |
*/ |
|
990 |
private static FieldPosition _fieldPosition = new FieldPosition(0); |
|
991 |
||
992 |
public static String formatNumber(double number, String pattern, |
|
993 |
DecimalFormat formatter) { |
|
994 |
// bugzilla fix 12813 |
|
995 |
if (formatter == null) { |
|
996 |
formatter = defaultFormatter; |
|
997 |
} |
|
998 |
try { |
|
999 |
StringBuffer result = threadLocalStringBuffer.get(); |
|
1000 |
result.setLength(0); |
|
1001 |
if (pattern != defaultPattern) { |
|
1002 |
formatter.applyLocalizedPattern(pattern); |
|
1003 |
} |
|
1004 |
formatter.format(number, result, _fieldPosition); |
|
1005 |
return result.toString(); |
|
1006 |
} |
|
1007 |
catch (IllegalArgumentException e) { |
|
1008 |
runTimeError(FORMAT_NUMBER_ERR, Double.toString(number), pattern); |
|
1009 |
return(EMPTYSTRING); |
|
1010 |
} |
|
1011 |
} |
|
1012 |
||
1013 |
/** |
|
1014 |
* Utility function: used to convert references to node-sets. If the |
|
1015 |
* obj is an instanceof Node then create a singleton iterator. |
|
1016 |
*/ |
|
1017 |
public static DTMAxisIterator referenceToNodeSet(Object obj) { |
|
1018 |
// Convert var/param -> node |
|
1019 |
if (obj instanceof Node) { |
|
1020 |
return(new SingletonIterator(((Node)obj).node)); |
|
1021 |
} |
|
1022 |
// Convert var/param -> node-set |
|
1023 |
else if (obj instanceof DTMAxisIterator) { |
|
12458 | 1024 |
return(((DTMAxisIterator)obj).cloneIterator().reset()); |
12005 | 1025 |
} |
1026 |
else { |
|
1027 |
final String className = obj.getClass().getName(); |
|
1028 |
runTimeError(DATA_CONVERSION_ERR, className, "node-set"); |
|
1029 |
return null; |
|
1030 |
} |
|
1031 |
} |
|
1032 |
||
1033 |
/** |
|
1034 |
* Utility function: used to convert reference to org.w3c.dom.NodeList. |
|
1035 |
*/ |
|
1036 |
public static NodeList referenceToNodeList(Object obj, DOM dom) { |
|
1037 |
if (obj instanceof Node || obj instanceof DTMAxisIterator) { |
|
1038 |
DTMAxisIterator iter = referenceToNodeSet(obj); |
|
1039 |
return dom.makeNodeList(iter); |
|
1040 |
} |
|
1041 |
else if (obj instanceof DOM) { |
|
1042 |
dom = (DOM)obj; |
|
1043 |
return dom.makeNodeList(DTMDefaultBase.ROOTNODE); |
|
1044 |
} |
|
1045 |
else { |
|
1046 |
final String className = obj.getClass().getName(); |
|
1047 |
runTimeError(DATA_CONVERSION_ERR, className, |
|
1048 |
"org.w3c.dom.NodeList"); |
|
1049 |
return null; |
|
1050 |
} |
|
1051 |
} |
|
1052 |
||
1053 |
/** |
|
1054 |
* Utility function: used to convert reference to org.w3c.dom.Node. |
|
1055 |
*/ |
|
1056 |
public static org.w3c.dom.Node referenceToNode(Object obj, DOM dom) { |
|
1057 |
if (obj instanceof Node || obj instanceof DTMAxisIterator) { |
|
1058 |
DTMAxisIterator iter = referenceToNodeSet(obj); |
|
1059 |
return dom.makeNode(iter); |
|
1060 |
} |
|
1061 |
else if (obj instanceof DOM) { |
|
1062 |
dom = (DOM)obj; |
|
1063 |
DTMAxisIterator iter = dom.getChildren(DTMDefaultBase.ROOTNODE); |
|
1064 |
return dom.makeNode(iter); |
|
1065 |
} |
|
1066 |
else { |
|
1067 |
final String className = obj.getClass().getName(); |
|
1068 |
runTimeError(DATA_CONVERSION_ERR, className, "org.w3c.dom.Node"); |
|
1069 |
return null; |
|
1070 |
} |
|
1071 |
} |
|
1072 |
||
1073 |
/** |
|
1074 |
* Utility function: used to convert reference to long. |
|
1075 |
*/ |
|
1076 |
public static long referenceToLong(Object obj) { |
|
1077 |
if (obj instanceof Number) { |
|
1078 |
return ((Number) obj).longValue(); // handles Integer and Double |
|
1079 |
} |
|
1080 |
else { |
|
1081 |
final String className = obj.getClass().getName(); |
|
1082 |
runTimeError(DATA_CONVERSION_ERR, className, Long.TYPE); |
|
1083 |
return 0; |
|
1084 |
} |
|
1085 |
} |
|
1086 |
||
1087 |
/** |
|
1088 |
* Utility function: used to convert reference to double. |
|
1089 |
*/ |
|
1090 |
public static double referenceToDouble(Object obj) { |
|
1091 |
if (obj instanceof Number) { |
|
1092 |
return ((Number) obj).doubleValue(); // handles Integer and Double |
|
1093 |
} |
|
1094 |
else { |
|
1095 |
final String className = obj.getClass().getName(); |
|
1096 |
runTimeError(DATA_CONVERSION_ERR, className, Double.TYPE); |
|
1097 |
return 0; |
|
1098 |
} |
|
1099 |
} |
|
1100 |
||
1101 |
/** |
|
1102 |
* Utility function: used to convert reference to boolean. |
|
1103 |
*/ |
|
1104 |
public static boolean referenceToBoolean(Object obj) { |
|
1105 |
if (obj instanceof Boolean) { |
|
1106 |
return ((Boolean) obj).booleanValue(); |
|
1107 |
} |
|
1108 |
else { |
|
1109 |
final String className = obj.getClass().getName(); |
|
1110 |
runTimeError(DATA_CONVERSION_ERR, className, Boolean.TYPE); |
|
1111 |
return false; |
|
1112 |
} |
|
1113 |
} |
|
1114 |
||
1115 |
/** |
|
1116 |
* Utility function: used to convert reference to String. |
|
1117 |
*/ |
|
1118 |
public static String referenceToString(Object obj, DOM dom) { |
|
1119 |
if (obj instanceof String) { |
|
1120 |
return (String) obj; |
|
1121 |
} |
|
1122 |
else if (obj instanceof DTMAxisIterator) { |
|
1123 |
return dom.getStringValueX(((DTMAxisIterator)obj).reset().next()); |
|
1124 |
} |
|
1125 |
else if (obj instanceof Node) { |
|
1126 |
return dom.getStringValueX(((Node)obj).node); |
|
1127 |
} |
|
1128 |
else if (obj instanceof DOM) { |
|
1129 |
return ((DOM) obj).getStringValue(); |
|
1130 |
} |
|
1131 |
else { |
|
1132 |
final String className = obj.getClass().getName(); |
|
1133 |
runTimeError(DATA_CONVERSION_ERR, className, String.class); |
|
1134 |
return null; |
|
1135 |
} |
|
1136 |
} |
|
1137 |
||
1138 |
/** |
|
1139 |
* Utility function used to convert a w3c Node into an internal DOM iterator. |
|
1140 |
*/ |
|
1141 |
public static DTMAxisIterator node2Iterator(org.w3c.dom.Node node, |
|
1142 |
Translet translet, DOM dom) |
|
1143 |
{ |
|
1144 |
final org.w3c.dom.Node inNode = node; |
|
1145 |
// Create a dummy NodeList which only contains the given node to make |
|
1146 |
// use of the nodeList2Iterator() interface. |
|
1147 |
org.w3c.dom.NodeList nodelist = new org.w3c.dom.NodeList() { |
|
1148 |
public int getLength() { |
|
1149 |
return 1; |
|
1150 |
} |
|
1151 |
||
1152 |
public org.w3c.dom.Node item(int index) { |
|
1153 |
if (index == 0) |
|
1154 |
return inNode; |
|
1155 |
else |
|
1156 |
return null; |
|
1157 |
} |
|
1158 |
}; |
|
1159 |
||
1160 |
return nodeList2Iterator(nodelist, translet, dom); |
|
1161 |
} |
|
1162 |
||
1163 |
/** |
|
12458 | 1164 |
* In a perfect world, this would be the implementation for |
1165 |
* nodeList2Iterator. In reality, though, this causes a |
|
1166 |
* ClassCastException in getDTMHandleFromNode because SAXImpl is |
|
1167 |
* not an instance of DOM2DTM. So we use the more lengthy |
|
1168 |
* implementation below until this issue has been addressed. |
|
1169 |
* |
|
1170 |
* @see org.apache.xml.dtm.ref.DTMManagerDefault#getDTMHandleFromNode |
|
12005 | 1171 |
*/ |
12458 | 1172 |
private static DTMAxisIterator nodeList2IteratorUsingHandleFromNode( |
1173 |
org.w3c.dom.NodeList nodeList, |
|
1174 |
Translet translet, DOM dom) |
|
12005 | 1175 |
{ |
12458 | 1176 |
final int n = nodeList.getLength(); |
1177 |
final int[] dtmHandles = new int[n]; |
|
1178 |
DTMManager dtmManager = null; |
|
1179 |
if (dom instanceof MultiDOM) |
|
1180 |
dtmManager = ((MultiDOM) dom).getDTMManager(); |
|
1181 |
for (int i = 0; i < n; ++i) { |
|
1182 |
org.w3c.dom.Node node = nodeList.item(i); |
|
1183 |
int handle; |
|
1184 |
if (dtmManager != null) { |
|
1185 |
handle = dtmManager.getDTMHandleFromNode(node); |
|
12005 | 1186 |
} |
12458 | 1187 |
else if (node instanceof DTMNodeProxy |
1188 |
&& ((DTMNodeProxy) node).getDTM() == dom) { |
|
1189 |
handle = ((DTMNodeProxy) node).getDTMNodeNumber(); |
|
12005 | 1190 |
} |
12458 | 1191 |
else { |
1192 |
runTimeError(RUN_TIME_INTERNAL_ERR, "need MultiDOM"); |
|
1193 |
return null; |
|
12005 | 1194 |
} |
12458 | 1195 |
dtmHandles[i] = handle; |
1196 |
System.out.println("Node " + i + " has handle 0x" + |
|
1197 |
Integer.toString(handle, 16)); |
|
12005 | 1198 |
} |
12458 | 1199 |
return new ArrayNodeListIterator(dtmHandles); |
12005 | 1200 |
} |
1201 |
||
1202 |
/** |
|
1203 |
* Utility function used to convert a w3c NodeList into a internal |
|
1204 |
* DOM iterator. |
|
1205 |
*/ |
|
1206 |
public static DTMAxisIterator nodeList2Iterator( |
|
1207 |
org.w3c.dom.NodeList nodeList, |
|
1208 |
Translet translet, DOM dom) |
|
1209 |
{ |
|
12458 | 1210 |
// First pass: build w3c DOM for all nodes not proxied from our DOM. |
1211 |
// |
|
1212 |
// Notice: this looses some (esp. parent) context for these nodes, |
|
1213 |
// so some way to wrap the original nodes inside a DTMAxisIterator |
|
1214 |
// might be preferable in the long run. |
|
1215 |
int n = 0; // allow for change in list length, just in case. |
|
12005 | 1216 |
Document doc = null; |
12458 | 1217 |
DTMManager dtmManager = null; |
1218 |
int[] proxyNodes = new int[nodeList.getLength()]; |
|
1219 |
if (dom instanceof MultiDOM) |
|
1220 |
dtmManager = ((MultiDOM) dom).getDTMManager(); |
|
1221 |
for (int i = 0; i < nodeList.getLength(); ++i) { |
|
1222 |
org.w3c.dom.Node node = nodeList.item(i); |
|
1223 |
if (node instanceof DTMNodeProxy) { |
|
1224 |
DTMNodeProxy proxy = (DTMNodeProxy)node; |
|
1225 |
DTM nodeDTM = proxy.getDTM(); |
|
1226 |
int handle = proxy.getDTMNodeNumber(); |
|
1227 |
boolean isOurDOM = (nodeDTM == dom); |
|
1228 |
if (!isOurDOM && dtmManager != null) { |
|
1229 |
try { |
|
1230 |
isOurDOM = (nodeDTM == dtmManager.getDTM(handle)); |
|
1231 |
} |
|
1232 |
catch (ArrayIndexOutOfBoundsException e) { |
|
1233 |
// invalid node handle, so definitely not our doc |
|
1234 |
} |
|
1235 |
} |
|
1236 |
if (isOurDOM) { |
|
1237 |
proxyNodes[i] = handle; |
|
1238 |
++n; |
|
1239 |
continue; |
|
1240 |
} |
|
1241 |
} |
|
1242 |
proxyNodes[i] = DTM.NULL; |
|
1243 |
int nodeType = node.getNodeType(); |
|
1244 |
if (doc == null) { |
|
1245 |
if (dom instanceof MultiDOM == false) { |
|
1246 |
runTimeError(RUN_TIME_INTERNAL_ERR, "need MultiDOM"); |
|
1247 |
return null; |
|
1248 |
} |
|
1249 |
try { |
|
1250 |
AbstractTranslet at = (AbstractTranslet) translet; |
|
1251 |
doc = at.newDocument("", "__top__"); |
|
1252 |
} |
|
1253 |
catch (javax.xml.parsers.ParserConfigurationException e) { |
|
1254 |
runTimeError(RUN_TIME_INTERNAL_ERR, e.getMessage()); |
|
1255 |
return null; |
|
1256 |
} |
|
1257 |
} |
|
1258 |
// Use one dummy element as container for each node of the |
|
1259 |
// list. That way, it is easier to detect resp. avoid |
|
1260 |
// funny things which change the number of nodes, |
|
1261 |
// e.g. auto-concatenation of text nodes. |
|
1262 |
Element mid; |
|
1263 |
switch (nodeType) { |
|
1264 |
case org.w3c.dom.Node.ELEMENT_NODE: |
|
1265 |
case org.w3c.dom.Node.TEXT_NODE: |
|
1266 |
case org.w3c.dom.Node.CDATA_SECTION_NODE: |
|
1267 |
case org.w3c.dom.Node.COMMENT_NODE: |
|
1268 |
case org.w3c.dom.Node.ENTITY_REFERENCE_NODE: |
|
1269 |
case org.w3c.dom.Node.PROCESSING_INSTRUCTION_NODE: |
|
1270 |
mid = doc.createElementNS(null, "__dummy__"); |
|
1271 |
mid.appendChild(doc.importNode(node, true)); |
|
1272 |
doc.getDocumentElement().appendChild(mid); |
|
1273 |
++n; |
|
1274 |
break; |
|
1275 |
case org.w3c.dom.Node.ATTRIBUTE_NODE: |
|
1276 |
// The mid element also serves as a container for |
|
1277 |
// attributes, avoiding problems with conflicting |
|
1278 |
// attributes or node order. |
|
1279 |
mid = doc.createElementNS(null, "__dummy__"); |
|
1280 |
mid.setAttributeNodeNS((Attr)doc.importNode(node, true)); |
|
1281 |
doc.getDocumentElement().appendChild(mid); |
|
1282 |
++n; |
|
1283 |
break; |
|
1284 |
default: |
|
1285 |
// Better play it safe for all types we aren't sure we know |
|
1286 |
// how to deal with. |
|
1287 |
runTimeError(RUN_TIME_INTERNAL_ERR, |
|
1288 |
"Don't know how to convert node type " |
|
1289 |
+ nodeType); |
|
1290 |
} |
|
12005 | 1291 |
} |
1292 |
||
1293 |
// w3cDOM -> DTM -> DOMImpl |
|
12458 | 1294 |
DTMAxisIterator iter = null, childIter = null, attrIter = null; |
1295 |
if (doc != null) { |
|
12005 | 1296 |
final MultiDOM multiDOM = (MultiDOM) dom; |
1297 |
DOM idom = (DOM)dtmManager.getDTM(new DOMSource(doc), false, |
|
1298 |
null, true, false); |
|
1299 |
// Create DOMAdapter and register with MultiDOM |
|
1300 |
DOMAdapter domAdapter = new DOMAdapter(idom, |
|
1301 |
translet.getNamesArray(), |
|
1302 |
translet.getUrisArray(), |
|
1303 |
translet.getTypesArray(), |
|
1304 |
translet.getNamespaceArray()); |
|
1305 |
multiDOM.addDOMAdapter(domAdapter); |
|
1306 |
||
1307 |
DTMAxisIterator iter1 = idom.getAxisIterator(Axis.CHILD); |
|
1308 |
DTMAxisIterator iter2 = idom.getAxisIterator(Axis.CHILD); |
|
12458 | 1309 |
iter = new AbsoluteIterator( |
12005 | 1310 |
new StepIterator(iter1, iter2)); |
1311 |
||
1312 |
iter.setStartNode(DTMDefaultBase.ROOTNODE); |
|
12458 | 1313 |
|
1314 |
childIter = idom.getAxisIterator(Axis.CHILD); |
|
1315 |
attrIter = idom.getAxisIterator(Axis.ATTRIBUTE); |
|
12005 | 1316 |
} |
12458 | 1317 |
|
1318 |
// Second pass: find DTM handles for every node in the list. |
|
1319 |
int[] dtmHandles = new int[n]; |
|
1320 |
n = 0; |
|
1321 |
for (int i = 0; i < nodeList.getLength(); ++i) { |
|
1322 |
if (proxyNodes[i] != DTM.NULL) { |
|
1323 |
dtmHandles[n++] = proxyNodes[i]; |
|
1324 |
continue; |
|
1325 |
} |
|
1326 |
org.w3c.dom.Node node = nodeList.item(i); |
|
1327 |
DTMAxisIterator iter3 = null; |
|
1328 |
int nodeType = node.getNodeType(); |
|
1329 |
switch (nodeType) { |
|
1330 |
case org.w3c.dom.Node.ELEMENT_NODE: |
|
1331 |
case org.w3c.dom.Node.TEXT_NODE: |
|
1332 |
case org.w3c.dom.Node.CDATA_SECTION_NODE: |
|
1333 |
case org.w3c.dom.Node.COMMENT_NODE: |
|
1334 |
case org.w3c.dom.Node.ENTITY_REFERENCE_NODE: |
|
1335 |
case org.w3c.dom.Node.PROCESSING_INSTRUCTION_NODE: |
|
1336 |
iter3 = childIter; |
|
1337 |
break; |
|
1338 |
case org.w3c.dom.Node.ATTRIBUTE_NODE: |
|
1339 |
iter3 = attrIter; |
|
1340 |
break; |
|
1341 |
default: |
|
1342 |
// Should not happen, as first run should have got all these |
|
1343 |
throw new InternalRuntimeError("Mismatched cases"); |
|
1344 |
} |
|
1345 |
if (iter3 != null) { |
|
1346 |
iter3.setStartNode(iter.next()); |
|
1347 |
dtmHandles[n] = iter3.next(); |
|
1348 |
// For now, play it self and perform extra checks: |
|
1349 |
if (dtmHandles[n] == DTMAxisIterator.END) |
|
1350 |
throw new InternalRuntimeError("Expected element missing at " + i); |
|
1351 |
if (iter3.next() != DTMAxisIterator.END) |
|
1352 |
throw new InternalRuntimeError("Too many elements at " + i); |
|
1353 |
++n; |
|
1354 |
} |
|
12005 | 1355 |
} |
12458 | 1356 |
if (n != dtmHandles.length) |
1357 |
throw new InternalRuntimeError("Nodes lost in second pass"); |
|
1358 |
||
1359 |
return new ArrayNodeListIterator(dtmHandles); |
|
12005 | 1360 |
} |
1361 |
||
1362 |
/** |
|
1363 |
* Utility function used to convert references to DOMs. |
|
1364 |
*/ |
|
1365 |
public static DOM referenceToResultTree(Object obj) { |
|
1366 |
try { |
|
1367 |
return ((DOM) obj); |
|
1368 |
} |
|
1369 |
catch (IllegalArgumentException e) { |
|
1370 |
final String className = obj.getClass().getName(); |
|
1371 |
runTimeError(DATA_CONVERSION_ERR, "reference", className); |
|
1372 |
return null; |
|
1373 |
} |
|
1374 |
} |
|
1375 |
||
1376 |
/** |
|
1377 |
* Utility function: used with nth position filters to convert a sequence |
|
1378 |
* of nodes to just one single node (the one at position n). |
|
1379 |
*/ |
|
1380 |
public static DTMAxisIterator getSingleNode(DTMAxisIterator iterator) { |
|
1381 |
int node = iterator.next(); |
|
1382 |
return(new SingletonIterator(node)); |
|
1383 |
} |
|
1384 |
||
1385 |
/** |
|
1386 |
* Utility function: used in xsl:copy. |
|
1387 |
*/ |
|
1388 |
private static char[] _characterArray = new char[32]; |
|
1389 |
||
1390 |
public static void copy(Object obj, |
|
1391 |
SerializationHandler handler, |
|
1392 |
int node, |
|
1393 |
DOM dom) { |
|
1394 |
try { |
|
1395 |
if (obj instanceof DTMAxisIterator) |
|
1396 |
{ |
|
1397 |
DTMAxisIterator iter = (DTMAxisIterator) obj; |
|
1398 |
dom.copy(iter.reset(), handler); |
|
1399 |
} |
|
1400 |
else if (obj instanceof Node) { |
|
1401 |
dom.copy(((Node) obj).node, handler); |
|
1402 |
} |
|
1403 |
else if (obj instanceof DOM) { |
|
1404 |
//((DOM)obj).copy(((com.sun.org.apache.xml.internal.dtm.ref.DTMDefaultBase)((DOMAdapter)obj).getDOMImpl()).getDocument(), handler); |
|
1405 |
DOM newDom = (DOM)obj; |
|
1406 |
newDom.copy(newDom.getDocument(), handler); |
|
1407 |
} |
|
1408 |
else { |
|
1409 |
String string = obj.toString(); // or call stringF() |
|
1410 |
final int length = string.length(); |
|
1411 |
if (length > _characterArray.length) |
|
1412 |
_characterArray = new char[length]; |
|
1413 |
string.getChars(0, length, _characterArray, 0); |
|
1414 |
handler.characters(_characterArray, 0, length); |
|
1415 |
} |
|
1416 |
} |
|
1417 |
catch (SAXException e) { |
|
1418 |
runTimeError(RUN_TIME_COPY_ERR); |
|
1419 |
} |
|
1420 |
} |
|
1421 |
||
1422 |
/** |
|
1423 |
* Utility function to check if xsl:attribute has a valid qname |
|
1424 |
* This method should only be invoked if the name attribute is an AVT |
|
1425 |
*/ |
|
1426 |
public static void checkAttribQName(String name) { |
|
1427 |
final int firstOccur = name.indexOf(":"); |
|
1428 |
final int lastOccur = name.lastIndexOf(":"); |
|
1429 |
final String localName = name.substring(lastOccur + 1); |
|
1430 |
||
1431 |
if (firstOccur > 0) { |
|
1432 |
final String newPrefix = name.substring(0, firstOccur); |
|
1433 |
||
1434 |
if (firstOccur != lastOccur) { |
|
1435 |
final String oriPrefix = name.substring(firstOccur+1, lastOccur); |
|
1436 |
if (!XML11Char.isXML11ValidNCName(oriPrefix)) { |
|
1437 |
// even though the orignal prefix is ignored, it should still get checked for valid NCName |
|
1438 |
runTimeError(INVALID_QNAME_ERR,oriPrefix+":"+localName); |
|
1439 |
} |
|
1440 |
} |
|
1441 |
||
1442 |
// prefix must be a valid NCName |
|
1443 |
if (!XML11Char.isXML11ValidNCName(newPrefix)) { |
|
1444 |
runTimeError(INVALID_QNAME_ERR,newPrefix+":"+localName); |
|
1445 |
} |
|
1446 |
} |
|
1447 |
||
1448 |
// local name must be a valid NCName and must not be XMLNS |
|
1449 |
if ((!XML11Char.isXML11ValidNCName(localName))||(localName.equals(Constants.XMLNS_PREFIX))) { |
|
1450 |
runTimeError(INVALID_QNAME_ERR,localName); |
|
1451 |
} |
|
1452 |
} |
|
1453 |
||
1454 |
/** |
|
1455 |
* Utility function to check if a name is a valid ncname |
|
1456 |
* This method should only be invoked if the attribute value is an AVT |
|
1457 |
*/ |
|
1458 |
public static void checkNCName(String name) { |
|
1459 |
if (!XML11Char.isXML11ValidNCName(name)) { |
|
1460 |
runTimeError(INVALID_NCNAME_ERR,name); |
|
1461 |
} |
|
1462 |
} |
|
1463 |
||
1464 |
/** |
|
1465 |
* Utility function to check if a name is a valid qname |
|
1466 |
* This method should only be invoked if the attribute value is an AVT |
|
1467 |
*/ |
|
1468 |
public static void checkQName(String name) { |
|
1469 |
if (!XML11Char.isXML11ValidQName(name)) { |
|
1470 |
runTimeError(INVALID_QNAME_ERR,name); |
|
1471 |
} |
|
1472 |
} |
|
1473 |
||
1474 |
/** |
|
1475 |
* Utility function for the implementation of xsl:element. |
|
1476 |
*/ |
|
1477 |
public static String startXslElement(String qname, String namespace, |
|
1478 |
SerializationHandler handler, DOM dom, int node) |
|
1479 |
{ |
|
1480 |
try { |
|
1481 |
// Get prefix from qname |
|
1482 |
String prefix; |
|
1483 |
final int index = qname.indexOf(':'); |
|
1484 |
||
1485 |
if (index > 0) { |
|
1486 |
prefix = qname.substring(0, index); |
|
1487 |
||
1488 |
// Handle case when prefix is not known at compile time |
|
1489 |
if (namespace == null || namespace.length() == 0) { |
|
1490 |
try { |
|
1491 |
// not sure if this line of code ever works |
|
1492 |
namespace = dom.lookupNamespace(node, prefix); |
|
1493 |
} |
|
1494 |
catch(RuntimeException e) { |
|
1495 |
handler.flushPending(); // need to flush or else can't get namespacemappings |
|
1496 |
NamespaceMappings nm = handler.getNamespaceMappings(); |
|
1497 |
namespace = nm.lookupNamespace(prefix); |
|
1498 |
if (namespace == null) { |
|
1499 |
runTimeError(NAMESPACE_PREFIX_ERR,prefix); |
|
1500 |
} |
|
1501 |
} |
|
1502 |
} |
|
1503 |
||
1504 |
handler.startElement(namespace, qname.substring(index+1), |
|
1505 |
qname); |
|
1506 |
handler.namespaceAfterStartElement(prefix, namespace); |
|
1507 |
} |
|
1508 |
else { |
|
1509 |
// Need to generate a prefix? |
|
1510 |
if (namespace != null && namespace.length() > 0) { |
|
1511 |
prefix = generatePrefix(); |
|
1512 |
qname = prefix + ':' + qname; |
|
1513 |
handler.startElement(namespace, qname, qname); |
|
1514 |
handler.namespaceAfterStartElement(prefix, namespace); |
|
1515 |
} |
|
1516 |
else { |
|
1517 |
handler.startElement(null, null, qname); |
|
1518 |
} |
|
1519 |
} |
|
1520 |
} |
|
1521 |
catch (SAXException e) { |
|
1522 |
throw new RuntimeException(e.getMessage()); |
|
1523 |
} |
|
1524 |
||
1525 |
return qname; |
|
1526 |
} |
|
1527 |
||
1528 |
/** |
|
1529 |
* This function is used in the execution of xsl:element |
|
1530 |
*/ |
|
1531 |
public static String getPrefix(String qname) { |
|
1532 |
final int index = qname.indexOf(':'); |
|
1533 |
return (index > 0) ? qname.substring(0, index) : null; |
|
1534 |
} |
|
1535 |
||
1536 |
/** |
|
41623
d32a755d06d1
8167179: Make XSL generated namespace prefixes local to transformation process
aefimov
parents:
33349
diff
changeset
|
1537 |
* These functions are used in the execution of xsl:element to generate |
d32a755d06d1
8167179: Make XSL generated namespace prefixes local to transformation process
aefimov
parents:
33349
diff
changeset
|
1538 |
* and reset namespace prefix index local to current transformation process |
12005 | 1539 |
*/ |
1540 |
public static String generatePrefix() { |
|
41623
d32a755d06d1
8167179: Make XSL generated namespace prefixes local to transformation process
aefimov
parents:
33349
diff
changeset
|
1541 |
return ("ns" + threadLocalPrefixIndex.get().getAndIncrement()); |
d32a755d06d1
8167179: Make XSL generated namespace prefixes local to transformation process
aefimov
parents:
33349
diff
changeset
|
1542 |
} |
d32a755d06d1
8167179: Make XSL generated namespace prefixes local to transformation process
aefimov
parents:
33349
diff
changeset
|
1543 |
|
d32a755d06d1
8167179: Make XSL generated namespace prefixes local to transformation process
aefimov
parents:
33349
diff
changeset
|
1544 |
public static void resetPrefixIndex() { |
d32a755d06d1
8167179: Make XSL generated namespace prefixes local to transformation process
aefimov
parents:
33349
diff
changeset
|
1545 |
threadLocalPrefixIndex.get().set(0); |
12005 | 1546 |
} |
1547 |
||
41623
d32a755d06d1
8167179: Make XSL generated namespace prefixes local to transformation process
aefimov
parents:
33349
diff
changeset
|
1548 |
private static final ThreadLocal<AtomicInteger> threadLocalPrefixIndex = |
d32a755d06d1
8167179: Make XSL generated namespace prefixes local to transformation process
aefimov
parents:
33349
diff
changeset
|
1549 |
new ThreadLocal<AtomicInteger>() { |
d32a755d06d1
8167179: Make XSL generated namespace prefixes local to transformation process
aefimov
parents:
33349
diff
changeset
|
1550 |
@Override |
d32a755d06d1
8167179: Make XSL generated namespace prefixes local to transformation process
aefimov
parents:
33349
diff
changeset
|
1551 |
protected AtomicInteger initialValue() { |
d32a755d06d1
8167179: Make XSL generated namespace prefixes local to transformation process
aefimov
parents:
33349
diff
changeset
|
1552 |
return new AtomicInteger(); |
d32a755d06d1
8167179: Make XSL generated namespace prefixes local to transformation process
aefimov
parents:
33349
diff
changeset
|
1553 |
} |
d32a755d06d1
8167179: Make XSL generated namespace prefixes local to transformation process
aefimov
parents:
33349
diff
changeset
|
1554 |
}; |
d32a755d06d1
8167179: Make XSL generated namespace prefixes local to transformation process
aefimov
parents:
33349
diff
changeset
|
1555 |
|
12005 | 1556 |
public static final String RUN_TIME_INTERNAL_ERR = |
1557 |
"RUN_TIME_INTERNAL_ERR"; |
|
1558 |
public static final String RUN_TIME_COPY_ERR = |
|
1559 |
"RUN_TIME_COPY_ERR"; |
|
1560 |
public static final String DATA_CONVERSION_ERR = |
|
1561 |
"DATA_CONVERSION_ERR"; |
|
1562 |
public static final String EXTERNAL_FUNC_ERR = |
|
1563 |
"EXTERNAL_FUNC_ERR"; |
|
1564 |
public static final String EQUALITY_EXPR_ERR = |
|
1565 |
"EQUALITY_EXPR_ERR"; |
|
1566 |
public static final String INVALID_ARGUMENT_ERR = |
|
1567 |
"INVALID_ARGUMENT_ERR"; |
|
1568 |
public static final String FORMAT_NUMBER_ERR = |
|
1569 |
"FORMAT_NUMBER_ERR"; |
|
1570 |
public static final String ITERATOR_CLONE_ERR = |
|
1571 |
"ITERATOR_CLONE_ERR"; |
|
1572 |
public static final String AXIS_SUPPORT_ERR = |
|
1573 |
"AXIS_SUPPORT_ERR"; |
|
1574 |
public static final String TYPED_AXIS_SUPPORT_ERR = |
|
1575 |
"TYPED_AXIS_SUPPORT_ERR"; |
|
1576 |
public static final String STRAY_ATTRIBUTE_ERR = |
|
1577 |
"STRAY_ATTRIBUTE_ERR"; |
|
1578 |
public static final String STRAY_NAMESPACE_ERR = |
|
1579 |
"STRAY_NAMESPACE_ERR"; |
|
1580 |
public static final String NAMESPACE_PREFIX_ERR = |
|
1581 |
"NAMESPACE_PREFIX_ERR"; |
|
1582 |
public static final String DOM_ADAPTER_INIT_ERR = |
|
1583 |
"DOM_ADAPTER_INIT_ERR"; |
|
1584 |
public static final String PARSER_DTD_SUPPORT_ERR = |
|
1585 |
"PARSER_DTD_SUPPORT_ERR"; |
|
1586 |
public static final String NAMESPACES_SUPPORT_ERR = |
|
1587 |
"NAMESPACES_SUPPORT_ERR"; |
|
1588 |
public static final String CANT_RESOLVE_RELATIVE_URI_ERR = |
|
1589 |
"CANT_RESOLVE_RELATIVE_URI_ERR"; |
|
1590 |
public static final String UNSUPPORTED_XSL_ERR = |
|
1591 |
"UNSUPPORTED_XSL_ERR"; |
|
1592 |
public static final String UNSUPPORTED_EXT_ERR = |
|
1593 |
"UNSUPPORTED_EXT_ERR"; |
|
1594 |
public static final String UNKNOWN_TRANSLET_VERSION_ERR = |
|
1595 |
"UNKNOWN_TRANSLET_VERSION_ERR"; |
|
1596 |
public static final String INVALID_QNAME_ERR = "INVALID_QNAME_ERR"; |
|
1597 |
public static final String INVALID_NCNAME_ERR = "INVALID_NCNAME_ERR"; |
|
1598 |
public static final String UNALLOWED_EXTENSION_FUNCTION_ERR = "UNALLOWED_EXTENSION_FUNCTION_ERR"; |
|
1599 |
public static final String UNALLOWED_EXTENSION_ELEMENT_ERR = "UNALLOWED_EXTENSION_ELEMENT_ERR"; |
|
1600 |
||
1601 |
// All error messages are localized and are stored in resource bundles. |
|
1602 |
private static ResourceBundle m_bundle; |
|
1603 |
||
1604 |
public final static String ERROR_MESSAGES_KEY = "error-messages"; |
|
1605 |
||
1606 |
static { |
|
1607 |
String resource = "com.sun.org.apache.xalan.internal.xsltc.runtime.ErrorMessages"; |
|
16953 | 1608 |
m_bundle = SecuritySupport.getResourceBundle(resource); |
12005 | 1609 |
} |
1610 |
||
1611 |
/** |
|
1612 |
* Print a run-time error message. |
|
1613 |
*/ |
|
1614 |
public static void runTimeError(String code) { |
|
1615 |
throw new RuntimeException(m_bundle.getString(code)); |
|
1616 |
} |
|
1617 |
||
1618 |
public static void runTimeError(String code, Object[] args) { |
|
1619 |
final String message = MessageFormat.format(m_bundle.getString(code), |
|
1620 |
args); |
|
1621 |
throw new RuntimeException(message); |
|
1622 |
} |
|
1623 |
||
1624 |
public static void runTimeError(String code, Object arg0) { |
|
1625 |
runTimeError(code, new Object[]{ arg0 } ); |
|
1626 |
} |
|
1627 |
||
1628 |
public static void runTimeError(String code, Object arg0, Object arg1) { |
|
1629 |
runTimeError(code, new Object[]{ arg0, arg1 } ); |
|
1630 |
} |
|
1631 |
||
1632 |
public static void consoleOutput(String msg) { |
|
1633 |
System.out.println(msg); |
|
1634 |
} |
|
1635 |
||
1636 |
/** |
|
1637 |
* Replace a certain character in a string with a new substring. |
|
1638 |
*/ |
|
1639 |
public static String replace(String base, char ch, String str) { |
|
1640 |
return (base.indexOf(ch) < 0) ? base : |
|
1641 |
replace(base, String.valueOf(ch), new String[] { str }); |
|
1642 |
} |
|
1643 |
||
1644 |
public static String replace(String base, String delim, String[] str) { |
|
1645 |
final int len = base.length(); |
|
1646 |
final StringBuilder result = threadLocalStringBuilder.get(); |
|
1647 |
result.setLength(0); |
|
1648 |
||
1649 |
for (int i = 0; i < len; i++) { |
|
1650 |
final char ch = base.charAt(i); |
|
1651 |
final int k = delim.indexOf(ch); |
|
1652 |
||
1653 |
if (k >= 0) { |
|
1654 |
result.append(str[k]); |
|
1655 |
} |
|
1656 |
else { |
|
1657 |
result.append(ch); |
|
1658 |
} |
|
1659 |
} |
|
1660 |
return result.toString(); |
|
1661 |
} |
|
1662 |
||
1663 |
||
1664 |
/** |
|
1665 |
* Utility method to allow setting parameters of the form |
|
1666 |
* {namespaceuri}localName |
|
1667 |
* which get mapped to an instance variable in the class |
|
1668 |
* Hence a parameter of the form "{http://foo.bar}xyz" |
|
1669 |
* will be replaced with the corresponding values |
|
1670 |
* by the BasisLibrary's utility method mapQNametoJavaName |
|
1671 |
* and thus get mapped to legal java variable names |
|
1672 |
*/ |
|
1673 |
public static String mapQNameToJavaName (String base ) { |
|
1674 |
return replace(base, ".-:/{}?#%*", |
|
1675 |
new String[] { "$dot$", "$dash$" ,"$colon$", "$slash$", |
|
1676 |
"","$colon$","$ques$","$hash$","$per$", |
|
1677 |
"$aster$"}); |
|
1678 |
||
1679 |
} |
|
1680 |
||
23092
64904fcdd0ee
8032909: XSLT string-length returns incorrect length when string includes complementary chars
aefimov
parents:
18356
diff
changeset
|
1681 |
/** |
64904fcdd0ee
8032909: XSLT string-length returns incorrect length when string includes complementary chars
aefimov
parents:
18356
diff
changeset
|
1682 |
* Utility method to calculate string-length as a number of code points, |
64904fcdd0ee
8032909: XSLT string-length returns incorrect length when string includes complementary chars
aefimov
parents:
18356
diff
changeset
|
1683 |
* to avoid possible errors with string that contains |
64904fcdd0ee
8032909: XSLT string-length returns incorrect length when string includes complementary chars
aefimov
parents:
18356
diff
changeset
|
1684 |
* complementary characters |
64904fcdd0ee
8032909: XSLT string-length returns incorrect length when string includes complementary chars
aefimov
parents:
18356
diff
changeset
|
1685 |
*/ |
64904fcdd0ee
8032909: XSLT string-length returns incorrect length when string includes complementary chars
aefimov
parents:
18356
diff
changeset
|
1686 |
public static int getStringLength(String str) { |
64904fcdd0ee
8032909: XSLT string-length returns incorrect length when string includes complementary chars
aefimov
parents:
18356
diff
changeset
|
1687 |
return str.codePointCount(0,str.length()); |
64904fcdd0ee
8032909: XSLT string-length returns incorrect length when string includes complementary chars
aefimov
parents:
18356
diff
changeset
|
1688 |
} |
64904fcdd0ee
8032909: XSLT string-length returns incorrect length when string includes complementary chars
aefimov
parents:
18356
diff
changeset
|
1689 |
|
12005 | 1690 |
//-- End utility functions |
1691 |
} |