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: BasisLibrary.java,v 1.76 2004/02/27 01:59:31 zongaro Exp $
  18. */
  19. package com.sun.org.apache.xalan.internal.xsltc.runtime;
  20. import java.text.DecimalFormat;
  21. import java.text.FieldPosition;
  22. import java.text.MessageFormat;
  23. import java.text.NumberFormat;
  24. import java.util.Locale;
  25. import java.util.ResourceBundle;
  26. import javax.xml.transform.dom.DOMSource;
  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.Axis;
  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.DTMAxisIterator;
  36. import com.sun.org.apache.xml.internal.dtm.DTMManager;
  37. import com.sun.org.apache.xml.internal.dtm.ref.DTMDefaultBase;
  38. import org.w3c.dom.DOMException;
  39. import org.w3c.dom.Document;
  40. import org.w3c.dom.NodeList;
  41. import org.xml.sax.SAXException;
  42. import com.sun.org.apache.xml.internal.serializer.NamespaceMappings;
  43. import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
  44. import com.sun.org.apache.xml.internal.utils.XMLChar;
  45. /**
  46. * Standard XSLT functions. All standard functions expect the current node
  47. * and the DOM as their last two arguments.
  48. */
  49. public final class BasisLibrary implements Operators {
  50. private final static String EMPTYSTRING = "";
  51. /**
  52. * Standard function count(node-set)
  53. */
  54. public static int countF(DTMAxisIterator iterator) {
  55. return(iterator.getLast());
  56. }
  57. /**
  58. * Standard function position()
  59. * @deprecated This method exists only for backwards compatibility with old
  60. * translets. New code should not reference it.
  61. */
  62. public static int positionF(DTMAxisIterator iterator) {
  63. return iterator.isReverse()
  64. ? iterator.getLast() - iterator.getPosition() + 1
  65. : iterator.getPosition();
  66. }
  67. /**
  68. * XSLT Standard function sum(node-set).
  69. * stringToDouble is inlined
  70. */
  71. public static double sumF(DTMAxisIterator iterator, DOM dom) {
  72. try {
  73. double result = 0.0;
  74. int node;
  75. while ((node = iterator.next()) != DTMAxisIterator.END) {
  76. result += Double.parseDouble(dom.getStringValueX(node));
  77. }
  78. return result;
  79. }
  80. catch (NumberFormatException e) {
  81. return Double.NaN;
  82. }
  83. }
  84. /**
  85. * XSLT Standard function string()
  86. */
  87. public static String stringF(int node, DOM dom) {
  88. return dom.getStringValueX(node);
  89. }
  90. /**
  91. * XSLT Standard function string(value)
  92. */
  93. public static String stringF(Object obj, DOM dom) {
  94. if (obj instanceof DTMAxisIterator) {
  95. return dom.getStringValueX(((DTMAxisIterator)obj).reset().next());
  96. }
  97. else if (obj instanceof Node) {
  98. return dom.getStringValueX(((Node)obj).node);
  99. }
  100. else if (obj instanceof DOM) {
  101. return ((DOM)obj).getStringValue();
  102. }
  103. else {
  104. return obj.toString();
  105. }
  106. }
  107. /**
  108. * XSLT Standard function string(value)
  109. */
  110. public static String stringF(Object obj, int node, DOM dom) {
  111. if (obj instanceof DTMAxisIterator) {
  112. return dom.getStringValueX(((DTMAxisIterator)obj).reset().next());
  113. }
  114. else if (obj instanceof Node) {
  115. return dom.getStringValueX(((Node)obj).node);
  116. }
  117. else if (obj instanceof DOM) {
  118. // When the first argument is a DOM we want the whole fecking
  119. // DOM and not just a single node - that would not make sense.
  120. //return ((DOM)obj).getStringValueX(node);
  121. return ((DOM)obj).getStringValue();
  122. }
  123. else if (obj instanceof Double) {
  124. Double d = (Double)obj;
  125. final String result = d.toString();
  126. final int length = result.length();
  127. if ((result.charAt(length-2)=='.') &&
  128. (result.charAt(length-1) == '0'))
  129. return result.substring(0, length-2);
  130. else
  131. return result;
  132. }
  133. else {
  134. if (obj != null)
  135. return obj.toString();
  136. else
  137. return stringF(node, dom);
  138. }
  139. }
  140. /**
  141. * XSLT Standard function number()
  142. */
  143. public static double numberF(int node, DOM dom) {
  144. return stringToReal(dom.getStringValueX(node));
  145. }
  146. /**
  147. * XSLT Standard function number(value)
  148. */
  149. public static double numberF(Object obj, DOM dom) {
  150. if (obj instanceof Double) {
  151. return ((Double) obj).doubleValue();
  152. }
  153. else if (obj instanceof Integer) {
  154. return ((Integer) obj).doubleValue();
  155. }
  156. else if (obj instanceof Boolean) {
  157. return ((Boolean) obj).booleanValue() ? 1.0 : 0.0;
  158. }
  159. else if (obj instanceof String) {
  160. return stringToReal((String) obj);
  161. }
  162. else if (obj instanceof DTMAxisIterator) {
  163. DTMAxisIterator iter = (DTMAxisIterator) obj;
  164. return stringToReal(dom.getStringValueX(iter.reset().next()));
  165. }
  166. else if (obj instanceof Node) {
  167. return stringToReal(dom.getStringValueX(((Node) obj).node));
  168. }
  169. else if (obj instanceof DOM) {
  170. return stringToReal(((DOM) obj).getStringValue());
  171. }
  172. else {
  173. final String className = obj.getClass().getName();
  174. runTimeError(INVALID_ARGUMENT_ERR, className, "number()");
  175. return 0.0;
  176. }
  177. }
  178. /**
  179. * XSLT Standard function round()
  180. */
  181. public static double roundF(double d) {
  182. return (d<-0.5 || d>0.0)?Math.floor(d+0.5):((d==0.0)?
  183. d:(Double.isNaN(d)?Double.NaN:-0.0));
  184. }
  185. /**
  186. * XSLT Standard function boolean()
  187. */
  188. public static boolean booleanF(Object obj) {
  189. if (obj instanceof Double) {
  190. final double temp = ((Double) obj).doubleValue();
  191. return temp != 0.0 && !Double.isNaN(temp);
  192. }
  193. else if (obj instanceof Integer) {
  194. return ((Integer) obj).doubleValue() != 0;
  195. }
  196. else if (obj instanceof Boolean) {
  197. return ((Boolean) obj).booleanValue();
  198. }
  199. else if (obj instanceof String) {
  200. return !((String) obj).equals(EMPTYSTRING);
  201. }
  202. else if (obj instanceof DTMAxisIterator) {
  203. DTMAxisIterator iter = (DTMAxisIterator) obj;
  204. return iter.reset().next() != DTMAxisIterator.END;
  205. }
  206. else if (obj instanceof Node) {
  207. return true;
  208. }
  209. else if (obj instanceof DOM) {
  210. String temp = ((DOM) obj).getStringValue();
  211. return !temp.equals(EMPTYSTRING);
  212. }
  213. else {
  214. final String className = obj.getClass().getName();
  215. runTimeError(INVALID_ARGUMENT_ERR, className, "number()");
  216. }
  217. return false;
  218. }
  219. /**
  220. * XSLT Standard function substring(). Must take a double because of
  221. * conversions resulting into NaNs and rounding.
  222. */
  223. public static String substringF(String value, double start) {
  224. try {
  225. final int strlen = value.length();
  226. int istart = (int)Math.round(start) - 1;
  227. if (Double.isNaN(start)) return(EMPTYSTRING);
  228. if (istart > strlen) return(EMPTYSTRING);
  229. if (istart < 1) istart = 0;
  230. return value.substring(istart);
  231. }
  232. catch (IndexOutOfBoundsException e) {
  233. runTimeError(RUN_TIME_INTERNAL_ERR, "substring()");
  234. return null;
  235. }
  236. }
  237. /**
  238. * XSLT Standard function substring(). Must take a double because of
  239. * conversions resulting into NaNs and rounding.
  240. */
  241. public static String substringF(String value, double start, double length) {
  242. try {
  243. final int strlen = value.length();
  244. int istart = (int)Math.round(start) - 1;
  245. int isum = istart + (int)Math.round(length);
  246. if (Double.isInfinite(length)) isum = Integer.MAX_VALUE;
  247. if (Double.isNaN(start) || Double.isNaN(length))
  248. return(EMPTYSTRING);
  249. if (Double.isInfinite(start)) return(EMPTYSTRING);
  250. if (istart > strlen) return(EMPTYSTRING);
  251. if (isum < 0) return(EMPTYSTRING);
  252. if (istart < 0) istart = 0;
  253. if (isum > strlen)
  254. return value.substring(istart);
  255. else
  256. return value.substring(istart, isum);
  257. }
  258. catch (IndexOutOfBoundsException e) {
  259. runTimeError(RUN_TIME_INTERNAL_ERR, "substring()");
  260. return null;
  261. }
  262. }
  263. /**
  264. * XSLT Standard function substring-after().
  265. */
  266. public static String substring_afterF(String value, String substring) {
  267. final int index = value.indexOf(substring);
  268. if (index >= 0)
  269. return value.substring(index + substring.length());
  270. else
  271. return EMPTYSTRING;
  272. }
  273. /**
  274. * XSLT Standard function substring-before().
  275. */
  276. public static String substring_beforeF(String value, String substring) {
  277. final int index = value.indexOf(substring);
  278. if (index >= 0)
  279. return value.substring(0, index);
  280. else
  281. return EMPTYSTRING;
  282. }
  283. /**
  284. * XSLT Standard function translate().
  285. */
  286. public static String translateF(String value, String from, String to) {
  287. final int tol = to.length();
  288. final int froml = from.length();
  289. final int valuel = value.length();
  290. final StringBuffer result = new StringBuffer();
  291. for (int j, i = 0; i < valuel; i++) {
  292. final char ch = value.charAt(i);
  293. for (j = 0; j < froml; j++) {
  294. if (ch == from.charAt(j)) {
  295. if (j < tol)
  296. result.append(to.charAt(j));
  297. break;
  298. }
  299. }
  300. if (j == froml)
  301. result.append(ch);
  302. }
  303. return result.toString();
  304. }
  305. /**
  306. * XSLT Standard function normalize-space().
  307. */
  308. public static String normalize_spaceF(int node, DOM dom) {
  309. return normalize_spaceF(dom.getStringValueX(node));
  310. }
  311. /**
  312. * XSLT Standard function normalize-space(string).
  313. */
  314. public static String normalize_spaceF(String value) {
  315. int i = 0, n = value.length();
  316. StringBuffer result = new StringBuffer();
  317. while (i < n && isWhiteSpace(value.charAt(i)))
  318. i++;
  319. while (true) {
  320. while (i < n && !isWhiteSpace(value.charAt(i))) {
  321. result.append(value.charAt(i++));
  322. }
  323. if (i == n)
  324. break;
  325. while (i < n && isWhiteSpace(value.charAt(i))) {
  326. i++;
  327. }
  328. if (i < n)
  329. result.append(' ');
  330. }
  331. return result.toString();
  332. }
  333. /**
  334. * XSLT Standard function generate-id().
  335. */
  336. public static String generate_idF(int node) {
  337. if (node > 0)
  338. // Only generate ID if node exists
  339. return "N" + node;
  340. else
  341. // Otherwise return an empty string
  342. return EMPTYSTRING;
  343. }
  344. /**
  345. * utility function for calls to local-name().
  346. */
  347. public static String getLocalName(String value) {
  348. int idx = value.lastIndexOf(':');
  349. if (idx >= 0) value = value.substring(idx + 1);
  350. idx = value.lastIndexOf('@');
  351. if (idx >= 0) value = value.substring(idx + 1);
  352. return(value);
  353. }
  354. /**
  355. * External functions that cannot be resolved are replaced with a call
  356. * to this method. This method will generate a runtime errors. A good
  357. * stylesheet checks whether the function exists using conditional
  358. * constructs, and never really tries to call it if it doesn't exist.
  359. * But simple stylesheets may result in a call to this method.
  360. * The compiler should generate a warning if it encounters a call to
  361. * an unresolved external function.
  362. */
  363. public static void unresolved_externalF(String name) {
  364. runTimeError(EXTERNAL_FUNC_ERR, name);
  365. }
  366. /**
  367. * Utility function to throw a runtime error for an unsupported element.
  368. *
  369. * This is only used in forward-compatibility mode, when the control flow
  370. * cannot be determined. In 1.0 mode, the error message is emitted at
  371. * compile time.
  372. */
  373. public static void unsupported_ElementF(String qname, boolean isExtension) {
  374. if (isExtension)
  375. runTimeError(UNSUPPORTED_EXT_ERR, qname);
  376. else
  377. runTimeError(UNSUPPORTED_XSL_ERR, qname);
  378. }
  379. /**
  380. * XSLT Standard function namespace-uri(node-set).
  381. */
  382. public static String namespace_uriF(DTMAxisIterator iter, DOM dom) {
  383. return namespace_uriF(iter.next(), dom);
  384. }
  385. /**
  386. * XSLT Standard function system-property(name)
  387. */
  388. public static String system_propertyF(String name) {
  389. if (name.equals("xsl:version"))
  390. return("1.0");
  391. if (name.equals("xsl:vendor"))
  392. return("Apache Software Foundation (Xalan XSLTC)");
  393. if (name.equals("xsl:vendor-url"))
  394. return("http://xml.apache.org/xalan-j");
  395. runTimeError(INVALID_ARGUMENT_ERR, name, "system-property()");
  396. return(EMPTYSTRING);
  397. }
  398. /**
  399. * XSLT Standard function namespace-uri().
  400. */
  401. public static String namespace_uriF(int node, DOM dom) {
  402. final String value = dom.getNodeName(node);
  403. final int colon = value.lastIndexOf(':');
  404. if (colon >= 0)
  405. return value.substring(0, colon);
  406. else
  407. return EMPTYSTRING;
  408. }
  409. /**
  410. * Implements the object-type() extension function.
  411. *
  412. * @see <a href="http://www.exslt.org/">EXSLT</a>
  413. */
  414. public static String objectTypeF(Object obj)
  415. {
  416. if (obj instanceof String)
  417. return "string";
  418. else if (obj instanceof Boolean)
  419. return "boolean";
  420. else if (obj instanceof Number)
  421. return "number";
  422. else if (obj instanceof DOM)
  423. return "RTF";
  424. else if (obj instanceof DTMAxisIterator)
  425. return "node-set";
  426. else
  427. return "unknown";
  428. }
  429. /**
  430. * Implements the nodeset() extension function.
  431. */
  432. public static DTMAxisIterator nodesetF(Object obj) {
  433. if (obj instanceof DOM) {
  434. //final DOMAdapter adapter = (DOMAdapter) obj;
  435. final DOM dom = (DOM)obj;
  436. return new SingletonIterator(dom.getDocument(), true);
  437. }
  438. else if (obj instanceof DTMAxisIterator) {
  439. return (DTMAxisIterator) obj;
  440. }
  441. else {
  442. final String className = obj.getClass().getName();
  443. runTimeError(DATA_CONVERSION_ERR, "node-set", className);
  444. return null;
  445. }
  446. }
  447. //-- Begin utility functions
  448. private static boolean isWhiteSpace(char ch) {
  449. return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r';
  450. }
  451. private static boolean compareStrings(String lstring, String rstring,
  452. int op, DOM dom) {
  453. switch (op) {
  454. case EQ:
  455. return lstring.equals(rstring);
  456. case NE:
  457. return !lstring.equals(rstring);
  458. case GT:
  459. return numberF(lstring, dom) > numberF(rstring, dom);
  460. case LT:
  461. return numberF(lstring, dom) < numberF(rstring, dom);
  462. case GE:
  463. return numberF(lstring, dom) >= numberF(rstring, dom);
  464. case LE:
  465. return numberF(lstring, dom) <= numberF(rstring, dom);
  466. default:
  467. runTimeError(RUN_TIME_INTERNAL_ERR, "compare()");
  468. return false;
  469. }
  470. }
  471. /**
  472. * Utility function: node-set/node-set compare.
  473. */
  474. public static boolean compare(DTMAxisIterator left, DTMAxisIterator right,
  475. int op, DOM dom) {
  476. int lnode;
  477. left.reset();
  478. while ((lnode = left.next()) != DTMAxisIterator.END) {
  479. final String lvalue = dom.getStringValueX(lnode);
  480. int rnode;
  481. right.reset();
  482. while ((rnode = right.next()) != DTMAxisIterator.END) {
  483. // String value must be the same if both nodes are the same
  484. if (lnode == rnode) {
  485. if (op == EQ) {
  486. return true;
  487. } else if (op == NE) {
  488. continue;
  489. }
  490. }
  491. if (compareStrings(lvalue, dom.getStringValueX(rnode), op,
  492. dom)) {
  493. return true;
  494. }
  495. }
  496. }
  497. return false;
  498. }
  499. public static boolean compare(int node, DTMAxisIterator iterator,
  500. int op, DOM dom) {
  501. //iterator.reset();
  502. int rnode;
  503. String value;
  504. switch(op) {
  505. case EQ:
  506. rnode = iterator.next();
  507. if (rnode != DTMAxisIterator.END) {
  508. value = dom.getStringValueX(node);
  509. do {
  510. if (node == rnode
  511. || value.equals(dom.getStringValueX(rnode))) {
  512. return true;
  513. }
  514. } while ((rnode = iterator.next()) != DTMAxisIterator.END);
  515. }
  516. break;
  517. case NE:
  518. rnode = iterator.next();
  519. if (rnode != DTMAxisIterator.END) {
  520. value = dom.getStringValueX(node);
  521. do {
  522. if (node != rnode
  523. && !value.equals(dom.getStringValueX(rnode))) {
  524. return true;
  525. }
  526. } while ((rnode = iterator.next()) != DTMAxisIterator.END);
  527. }
  528. break;
  529. case LT:
  530. // Assume we're comparing document order here
  531. while ((rnode = iterator.next()) != DTMAxisIterator.END) {
  532. if (rnode > node) return true;
  533. }
  534. break;
  535. case GT:
  536. // Assume we're comparing document order here
  537. while ((rnode = iterator.next()) != DTMAxisIterator.END) {
  538. if (rnode < node) return true;
  539. }
  540. break;
  541. }
  542. return(false);
  543. }
  544. /**
  545. * Utility function: node-set/number compare.
  546. */
  547. public static boolean compare(DTMAxisIterator left, final double rnumber,
  548. final int op, DOM dom) {
  549. int node;
  550. //left.reset();
  551. switch (op) {
  552. case EQ:
  553. while ((node = left.next()) != DTMAxisIterator.END) {
  554. if (numberF(dom.getStringValueX(node), dom) == rnumber)
  555. return true;
  556. }
  557. break;
  558. case NE:
  559. while ((node = left.next()) != DTMAxisIterator.END) {
  560. if (numberF(dom.getStringValueX(node), dom) != rnumber)
  561. return true;
  562. }
  563. break;
  564. case GT:
  565. while ((node = left.next()) != DTMAxisIterator.END) {
  566. if (numberF(dom.getStringValueX(node), dom) > rnumber)
  567. return true;
  568. }
  569. break;
  570. case LT:
  571. while ((node = left.next()) != DTMAxisIterator.END) {
  572. if (numberF(dom.getStringValueX(node), dom) < rnumber)
  573. return true;
  574. }
  575. break;
  576. case GE:
  577. while ((node = left.next()) != DTMAxisIterator.END) {
  578. if (numberF(dom.getStringValueX(node), dom) >= rnumber)
  579. return true;
  580. }
  581. break;
  582. case LE:
  583. while ((node = left.next()) != DTMAxisIterator.END) {
  584. if (numberF(dom.getStringValueX(node), dom) <= rnumber)
  585. return true;
  586. }
  587. break;
  588. default:
  589. runTimeError(RUN_TIME_INTERNAL_ERR, "compare()");
  590. }
  591. return false;
  592. }
  593. /**
  594. * Utility function: node-set/string comparison.
  595. */
  596. public static boolean compare(DTMAxisIterator left, final String rstring,
  597. int op, DOM dom) {
  598. int node;
  599. //left.reset();
  600. while ((node = left.next()) != DTMAxisIterator.END) {
  601. if (compareStrings(dom.getStringValueX(node), rstring, op, dom)) {
  602. return true;
  603. }
  604. }
  605. return false;
  606. }
  607. public static boolean compare(Object left, Object right,
  608. int op, DOM dom)
  609. {
  610. boolean result = false;
  611. boolean hasSimpleArgs = hasSimpleType(left) && hasSimpleType(right);
  612. if (op != EQ && op != NE) {
  613. // If node-boolean comparison -> convert node to boolean
  614. if (left instanceof Node || right instanceof Node) {
  615. if (left instanceof Boolean) {
  616. right = new Boolean(booleanF(right));
  617. hasSimpleArgs = true;
  618. }
  619. if (right instanceof Boolean) {
  620. left = new Boolean(booleanF(left));
  621. hasSimpleArgs = true;
  622. }
  623. }
  624. if (hasSimpleArgs) {
  625. switch (op) {
  626. case GT:
  627. return numberF(left, dom) > numberF(right, dom);
  628. case LT:
  629. return numberF(left, dom) < numberF(right, dom);
  630. case GE:
  631. return numberF(left, dom) >= numberF(right, dom);
  632. case LE:
  633. return numberF(left, dom) <= numberF(right, dom);
  634. default:
  635. runTimeError(RUN_TIME_INTERNAL_ERR, "compare()");
  636. }
  637. }
  638. // falls through
  639. }
  640. if (hasSimpleArgs) {
  641. if (left instanceof Boolean || right instanceof Boolean) {
  642. result = booleanF(left) == booleanF(right);
  643. }
  644. else if (left instanceof Double || right instanceof Double ||
  645. left instanceof Integer || right instanceof Integer) {
  646. result = numberF(left, dom) == numberF(right, dom);
  647. }
  648. else { // compare them as strings
  649. result = stringF(left, dom).equals(stringF(right, dom));
  650. }
  651. if (op == Operators.NE) {
  652. result = !result;
  653. }
  654. }
  655. else {
  656. if (left instanceof Node) {
  657. left = new SingletonIterator(((Node)left).node);
  658. }
  659. if (right instanceof Node) {
  660. right = new SingletonIterator(((Node)right).node);
  661. }
  662. if (hasSimpleType(left) ||
  663. left instanceof DOM && right instanceof DTMAxisIterator) {
  664. // swap operands
  665. final Object temp = right; right = left; left = temp;
  666. }
  667. if (left instanceof DOM) {
  668. if (right instanceof Boolean) {
  669. result = ((Boolean)right).booleanValue();
  670. return result == (op == Operators.EQ);
  671. }
  672. final String sleft = ((DOM)left).getStringValue();
  673. if (right instanceof Number) {
  674. result = ((Number)right).doubleValue() ==
  675. stringToReal(sleft);
  676. }
  677. else if (right instanceof String) {
  678. result = sleft.equals((String)right);
  679. }
  680. else if (right instanceof DOM) {
  681. result = sleft.equals(((DOM)right).getStringValue());
  682. }
  683. if (op == Operators.NE) {
  684. result = !result;
  685. }
  686. return result;
  687. }
  688. // Next, node-set/t for t in {real, string, node-set, result-tree}
  689. DTMAxisIterator iter = ((DTMAxisIterator)left).reset();
  690. if (right instanceof DTMAxisIterator) {
  691. result = compare(iter, (DTMAxisIterator)right, op, dom);
  692. }
  693. else if (right instanceof String) {
  694. result = compare(iter, (String)right, op, dom);
  695. }
  696. else if (right instanceof Number) {
  697. final double temp = ((Number)right).doubleValue();
  698. result = compare(iter, temp, op, dom);
  699. }
  700. else if (right instanceof Boolean) {
  701. boolean temp = ((Boolean)right).booleanValue();
  702. result = (iter.reset().next() != DTMAxisIterator.END) == temp;
  703. }
  704. else if (right instanceof DOM) {
  705. result = compare(iter, ((DOM)right).getStringValue(),
  706. op, dom);
  707. }
  708. else if (right == null) {
  709. return(false);
  710. }
  711. else {
  712. final String className = right.getClass().getName();
  713. runTimeError(INVALID_ARGUMENT_ERR, className, "compare()");
  714. }
  715. }
  716. return result;
  717. }
  718. /**
  719. * Utility function: used to test context node's language
  720. */
  721. public static boolean testLanguage(String testLang, DOM dom, int node) {
  722. // language for context node (if any)
  723. String nodeLang = dom.getLanguage(node);
  724. if (nodeLang == null)
  725. return(false);
  726. else
  727. nodeLang = nodeLang.toLowerCase();
  728. // compare context node's language agains test language
  729. testLang = testLang.toLowerCase();
  730. if (testLang.length() == 2) {
  731. return(nodeLang.startsWith(testLang));
  732. }
  733. else {
  734. return(nodeLang.equals(testLang));
  735. }
  736. }
  737. private static boolean hasSimpleType(Object obj) {
  738. return obj instanceof Boolean || obj instanceof Double ||
  739. obj instanceof Integer || obj instanceof String ||
  740. obj instanceof Node || obj instanceof DOM;
  741. }
  742. /**
  743. * Utility function: used in StringType to convert a string to a real.
  744. */
  745. public static double stringToReal(String s) {
  746. try {
  747. return Double.valueOf(s).doubleValue();
  748. }
  749. catch (NumberFormatException e) {
  750. return Double.NaN;
  751. }
  752. }
  753. /**
  754. * Utility function: used in StringType to convert a string to an int.
  755. */
  756. public static int stringToInt(String s) {
  757. try {
  758. return Integer.parseInt(s);
  759. }
  760. catch (NumberFormatException e) {
  761. return(-1); // ???
  762. }
  763. }
  764. private static final int DOUBLE_FRACTION_DIGITS = 340;
  765. private static final double lowerBounds = 0.001;
  766. private static final double upperBounds = 10000000;
  767. private static DecimalFormat defaultFormatter;
  768. private static String defaultPattern = "";
  769. static {
  770. NumberFormat f = NumberFormat.getInstance(Locale.getDefault());
  771. defaultFormatter = (f instanceof DecimalFormat) ?
  772. (DecimalFormat) f : new DecimalFormat();
  773. // Set max fraction digits so that truncation does not occur. Setting
  774. // the max to Integer.MAX_VALUE may cause problems with some JDK's.
  775. defaultFormatter.setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS);
  776. defaultFormatter.setMinimumFractionDigits(0);
  777. defaultFormatter.setMinimumIntegerDigits(1);
  778. defaultFormatter.setGroupingUsed(false);
  779. }
  780. /**
  781. * Utility function: used in RealType to convert a real to a string.
  782. * Removes the decimal if null.
  783. */
  784. public static String realToString(double d) {
  785. final double m = Math.abs(d);
  786. if ((m >= lowerBounds) && (m < upperBounds)) {
  787. final String result = Double.toString(d);
  788. final int length = result.length();
  789. // Remove leading zeros.
  790. if ((result.charAt(length-2) == '.') &&
  791. (result.charAt(length-1) == '0'))
  792. return result.substring(0, length-2);
  793. else
  794. return result;
  795. }
  796. else {
  797. if (Double.isNaN(d) || Double.isInfinite(d))
  798. return(Double.toString(d));
  799. return formatNumber(d, defaultPattern, defaultFormatter);
  800. }
  801. }
  802. /**
  803. * Utility function: used in RealType to convert a real to an integer
  804. */
  805. public static int realToInt(double d) {
  806. return (int)d;
  807. }
  808. /**
  809. * Utility function: used to format/adjust a double to a string. The
  810. * DecimalFormat object comes from the 'formatSymbols' hashtable in
  811. * AbstractTranslet.
  812. */
  813. private static FieldPosition _fieldPosition = new FieldPosition(0);
  814. public static String formatNumber(double number, String pattern,
  815. DecimalFormat formatter) {
  816. // bugzilla fix 12813
  817. if (formatter == null) {
  818. formatter = defaultFormatter;
  819. }
  820. try {
  821. StringBuffer result = new StringBuffer();
  822. if (pattern != defaultPattern) {
  823. formatter.applyLocalizedPattern(pattern);
  824. }
  825. formatter.format(number, result, _fieldPosition);
  826. return result.toString();
  827. }
  828. catch (IllegalArgumentException e) {
  829. runTimeError(FORMAT_NUMBER_ERR, Double.toString(number), pattern);
  830. return(EMPTYSTRING);
  831. }
  832. }
  833. /**
  834. * Utility function: used to convert references to node-sets. If the
  835. * obj is an instanceof Node then create a singleton iterator.
  836. */
  837. public static DTMAxisIterator referenceToNodeSet(Object obj) {
  838. // Convert var/param -> node
  839. if (obj instanceof Node) {
  840. return(new SingletonIterator(((Node)obj).node));
  841. }
  842. // Convert var/param -> node-set
  843. else if (obj instanceof DTMAxisIterator) {
  844. return(((DTMAxisIterator)obj).cloneIterator());
  845. }
  846. else {
  847. final String className = obj.getClass().getName();
  848. runTimeError(DATA_CONVERSION_ERR, className, "node-set");
  849. return null;
  850. }
  851. }
  852. /**
  853. * Utility function: used to convert reference to org.w3c.dom.NodeList.
  854. */
  855. public static NodeList referenceToNodeList(Object obj, DOM dom) {
  856. if (obj instanceof Node || obj instanceof DTMAxisIterator) {
  857. DTMAxisIterator iter = referenceToNodeSet(obj);
  858. return dom.makeNodeList(iter);
  859. }
  860. else if (obj instanceof DOM) {
  861. dom = (DOM)obj;
  862. return dom.makeNodeList(DTMDefaultBase.ROOTNODE);
  863. }
  864. else {
  865. final String className = obj.getClass().getName();
  866. runTimeError(DATA_CONVERSION_ERR, className,
  867. "org.w3c.dom.NodeList");
  868. return null;
  869. }
  870. }
  871. /**
  872. * Utility function: used to convert reference to org.w3c.dom.Node.
  873. */
  874. public static org.w3c.dom.Node referenceToNode(Object obj, DOM dom) {
  875. if (obj instanceof Node || obj instanceof DTMAxisIterator) {
  876. DTMAxisIterator iter = referenceToNodeSet(obj);
  877. return dom.makeNode(iter);
  878. }
  879. else if (obj instanceof DOM) {
  880. dom = (DOM)obj;
  881. DTMAxisIterator iter = dom.getChildren(DTMDefaultBase.ROOTNODE);
  882. return dom.makeNode(iter);
  883. }
  884. else {
  885. final String className = obj.getClass().getName();
  886. runTimeError(DATA_CONVERSION_ERR, className, "org.w3c.dom.Node");
  887. return null;
  888. }
  889. }
  890. /**
  891. * Utility function: used to convert reference to long.
  892. */
  893. public static long referenceToLong(Object obj) {
  894. if (obj instanceof Number) {
  895. return ((Number) obj).longValue(); // handles Integer and Double
  896. }
  897. else {
  898. final String className = obj.getClass().getName();
  899. runTimeError(DATA_CONVERSION_ERR, className, Long.TYPE);
  900. return 0;
  901. }
  902. }
  903. /**
  904. * Utility function: used to convert reference to double.
  905. */
  906. public static double referenceToDouble(Object obj) {
  907. if (obj instanceof Number) {
  908. return ((Number) obj).doubleValue(); // handles Integer and Double
  909. }
  910. else {
  911. final String className = obj.getClass().getName();
  912. runTimeError(DATA_CONVERSION_ERR, className, Double.TYPE);
  913. return 0;
  914. }
  915. }
  916. /**
  917. * Utility function: used to convert reference to boolean.
  918. */
  919. public static boolean referenceToBoolean(Object obj) {
  920. if (obj instanceof Boolean) {
  921. return ((Boolean) obj).booleanValue();
  922. }
  923. else {
  924. final String className = obj.getClass().getName();
  925. runTimeError(DATA_CONVERSION_ERR, className, Boolean.TYPE);
  926. return false;
  927. }
  928. }
  929. /**
  930. * Utility function: used to convert reference to String.
  931. */
  932. public static String referenceToString(Object obj, DOM dom) {
  933. if (obj instanceof String) {
  934. return (String) obj;
  935. }
  936. else if (obj instanceof DTMAxisIterator) {
  937. return dom.getStringValueX(((DTMAxisIterator)obj).reset().next());
  938. }
  939. else if (obj instanceof Node) {
  940. return dom.getStringValueX(((Node)obj).node);
  941. }
  942. else if (obj instanceof DOM) {
  943. return ((DOM) obj).getStringValue();
  944. }
  945. else {
  946. final String className = obj.getClass().getName();
  947. runTimeError(DATA_CONVERSION_ERR, className, String.class);
  948. return null;
  949. }
  950. }
  951. /**
  952. * Utility function used to convert a w3c Node into an internal DOM iterator.
  953. */
  954. public static DTMAxisIterator node2Iterator(org.w3c.dom.Node node,
  955. Translet translet, DOM dom)
  956. {
  957. final org.w3c.dom.Node inNode = node;
  958. // Create a dummy NodeList which only contains the given node to make
  959. // use of the nodeList2Iterator() interface.
  960. org.w3c.dom.NodeList nodelist = new org.w3c.dom.NodeList() {
  961. public int getLength() {
  962. return 1;
  963. }
  964. public org.w3c.dom.Node item(int index) {
  965. if (index == 0)
  966. return inNode;
  967. else
  968. return null;
  969. }
  970. };
  971. return nodeList2Iterator(nodelist, translet, dom);
  972. }
  973. /**
  974. * Utility function used to copy a node list to be under a parent node.
  975. */
  976. private static void copyNodes(org.w3c.dom.NodeList nodeList,
  977. org.w3c.dom.Document doc, org.w3c.dom.Node parent)
  978. {
  979. final int size = nodeList.getLength();
  980. // copy Nodes from NodeList into new w3c DOM
  981. for (int i = 0; i < size; i++)
  982. {
  983. org.w3c.dom.Node curr = nodeList.item(i);
  984. int nodeType = curr.getNodeType();
  985. String value = null;
  986. try {
  987. value = curr.getNodeValue();
  988. } catch (DOMException ex) {
  989. runTimeError(RUN_TIME_INTERNAL_ERR, ex.getMessage());
  990. return;
  991. }
  992. String nodeName = curr.getNodeName();
  993. org.w3c.dom.Node newNode = null;
  994. switch (nodeType){
  995. case org.w3c.dom.Node.ATTRIBUTE_NODE:
  996. newNode = doc.createAttributeNS(curr.getNamespaceURI(),
  997. nodeName);
  998. break;
  999. case org.w3c.dom.Node.CDATA_SECTION_NODE:
  1000. newNode = doc.createCDATASection(value);
  1001. break;
  1002. case org.w3c.dom.Node.COMMENT_NODE:
  1003. newNode = doc.createComment(value);
  1004. break;
  1005. case org.w3c.dom.Node.DOCUMENT_FRAGMENT_NODE:
  1006. newNode = doc.createDocumentFragment();
  1007. break;
  1008. case org.w3c.dom.Node.DOCUMENT_NODE:
  1009. newNode = doc.createElementNS(null, "__document__");
  1010. copyNodes(curr.getChildNodes(), doc, newNode);
  1011. break;
  1012. case org.w3c.dom.Node.DOCUMENT_TYPE_NODE:
  1013. // nothing?
  1014. break;
  1015. case org.w3c.dom.Node.ELEMENT_NODE:
  1016. // For Element node, also copy the children and the
  1017. // attributes.
  1018. org.w3c.dom.Element element = doc.createElementNS(
  1019. curr.getNamespaceURI(), nodeName);
  1020. if (curr.hasAttributes())
  1021. {
  1022. org.w3c.dom.NamedNodeMap attributes = curr.getAttributes();
  1023. for (int k = 0; k < attributes.getLength(); k++) {
  1024. org.w3c.dom.Node attr = attributes.item(k);
  1025. element.setAttributeNS(attr.getNamespaceURI(),
  1026. attr.getNodeName(), attr.getNodeValue());
  1027. }
  1028. }
  1029. copyNodes(curr.getChildNodes(), doc, element);
  1030. newNode = element;
  1031. break;
  1032. case org.w3c.dom.Node.ENTITY_NODE:
  1033. // nothing ?
  1034. break;
  1035. case org.w3c.dom.Node.ENTITY_REFERENCE_NODE:
  1036. newNode = doc.createEntityReference(nodeName);
  1037. break;
  1038. case org.w3c.dom.Node.NOTATION_NODE:
  1039. // nothing ?
  1040. break;
  1041. case org.w3c.dom.Node.PROCESSING_INSTRUCTION_NODE:
  1042. newNode = doc.createProcessingInstruction(nodeName,
  1043. value);
  1044. break;
  1045. case org.w3c.dom.Node.TEXT_NODE:
  1046. newNode = doc.createTextNode(value);
  1047. break;
  1048. }
  1049. try {
  1050. parent.appendChild(newNode);
  1051. } catch (DOMException e) {
  1052. runTimeError(RUN_TIME_INTERNAL_ERR, e.getMessage());
  1053. return;
  1054. }
  1055. }
  1056. }
  1057. /**
  1058. * Utility function used to convert a w3c NodeList into a internal
  1059. * DOM iterator.
  1060. */
  1061. public static DTMAxisIterator nodeList2Iterator(
  1062. org.w3c.dom.NodeList nodeList,
  1063. Translet translet, DOM dom)
  1064. {
  1065. // w3c NodeList -> w3c DOM
  1066. Document doc = null;
  1067. try {
  1068. doc = ((AbstractTranslet) translet).newDocument("", "__top__");
  1069. } catch (javax.xml.parsers.ParserConfigurationException e) {
  1070. runTimeError(RUN_TIME_INTERNAL_ERR, e.getMessage());
  1071. return null;
  1072. }
  1073. copyNodes(nodeList, doc, doc.getDocumentElement());
  1074. // w3cDOM -> DTM -> DOMImpl
  1075. if (dom instanceof MultiDOM) {
  1076. final MultiDOM multiDOM = (MultiDOM) dom;
  1077. DTMDefaultBase dtm = (DTMDefaultBase)((DOMAdapter)multiDOM.getMain()).getDOMImpl();
  1078. DTMManager dtmManager = dtm.getManager();
  1079. DOM idom = (DOM)dtmManager.getDTM(new DOMSource(doc), false,
  1080. null, true, false);
  1081. // Create DOMAdapter and register with MultiDOM
  1082. DOMAdapter domAdapter = new DOMAdapter(idom,
  1083. translet.getNamesArray(),
  1084. translet.getUrisArray(),
  1085. translet.getTypesArray(),
  1086. translet.getNamespaceArray());
  1087. multiDOM.addDOMAdapter(domAdapter);
  1088. DTMAxisIterator iter1 = idom.getAxisIterator(Axis.CHILD);
  1089. DTMAxisIterator iter2 = idom.getAxisIterator(Axis.CHILD);
  1090. DTMAxisIterator iter = new AbsoluteIterator(
  1091. new StepIterator(iter1, iter2));
  1092. iter.setStartNode(DTMDefaultBase.ROOTNODE);
  1093. return iter;
  1094. }
  1095. else {
  1096. runTimeError(RUN_TIME_INTERNAL_ERR, "nodeList2Iterator()");
  1097. return null;
  1098. }
  1099. }
  1100. /**
  1101. * Utility function used to convert references to DOMs.
  1102. */
  1103. public static DOM referenceToResultTree(Object obj) {
  1104. try {
  1105. return ((DOM) obj);
  1106. }
  1107. catch (IllegalArgumentException e) {
  1108. final String className = obj.getClass().getName();
  1109. runTimeError(DATA_CONVERSION_ERR, "reference", className);
  1110. return null;
  1111. }
  1112. }
  1113. /**
  1114. * Utility function: used with nth position filters to convert a sequence
  1115. * of nodes to just one single node (the one at position n).
  1116. */
  1117. public static DTMAxisIterator getSingleNode(DTMAxisIterator iterator) {
  1118. int node = iterator.next();
  1119. return(new SingletonIterator(node));
  1120. }
  1121. /**
  1122. * Utility function: used in xsl:copy.
  1123. */
  1124. private static char[] _characterArray = new char[32];
  1125. public static void copy(Object obj,
  1126. SerializationHandler handler,
  1127. int node,
  1128. DOM dom) {
  1129. try {
  1130. if (obj instanceof DTMAxisIterator)
  1131. {
  1132. DTMAxisIterator iter = (DTMAxisIterator) obj;
  1133. dom.copy(iter.reset(), handler);
  1134. }
  1135. else if (obj instanceof Node) {
  1136. dom.copy(((Node) obj).node, handler);
  1137. }
  1138. else if (obj instanceof DOM) {
  1139. //((DOM)obj).copy(((com.sun.org.apache.xml.internal.dtm.ref.DTMDefaultBase)((DOMAdapter)obj).getDOMImpl()).getDocument(), handler);
  1140. DOM newDom = (DOM)obj;
  1141. newDom.copy(newDom.getDocument(), handler);
  1142. }
  1143. else {
  1144. String string = obj.toString(); // or call stringF()
  1145. final int length = string.length();
  1146. if (length > _characterArray.length)
  1147. _characterArray = new char[length];
  1148. string.getChars(0, length, _characterArray, 0);
  1149. handler.characters(_characterArray, 0, length);
  1150. }
  1151. }
  1152. catch (SAXException e) {
  1153. runTimeError(RUN_TIME_COPY_ERR);
  1154. }
  1155. }
  1156. /**
  1157. * Utility function to check if xsl:attribute has a valid qname
  1158. * This method should only be invoked if the name attribute is an AVT
  1159. */
  1160. public static void checkAttribQName(String name) {
  1161. final int firstOccur = name.indexOf(":");
  1162. final int lastOccur = name.lastIndexOf(":");
  1163. final String localName = name.substring(lastOccur + 1);
  1164. if (firstOccur > 0) {
  1165. final String newPrefix = name.substring(0, firstOccur);
  1166. if (firstOccur != lastOccur) {
  1167. final String oriPrefix = name.substring(firstOccur+1, lastOccur);
  1168. if (!XMLChar.isValidNCName(oriPrefix)) {
  1169. // even though the orignal prefix is ignored, it should still get checked for valid NCName
  1170. runTimeError(INVALID_QNAME_ERR,oriPrefix+":"+localName);
  1171. }
  1172. }
  1173. // prefix must be a valid NCName
  1174. if (!XMLChar.isValidNCName(newPrefix)) {
  1175. runTimeError(INVALID_QNAME_ERR,newPrefix+":"+localName);
  1176. }
  1177. }
  1178. // local name must be a valid NCName and must not be XMLNS
  1179. if ((!XMLChar.isValidNCName(localName))||(localName.equals(Constants.XMLNS_PREFIX))) {
  1180. runTimeError(INVALID_QNAME_ERR,localName);
  1181. }
  1182. }
  1183. /**
  1184. * Utility function to check if a name is a valid ncname
  1185. * This method should only be invoked if the attribute value is an AVT
  1186. */
  1187. public static void checkNCName(String name) {
  1188. if (!XMLChar.isValidNCName(name)) {
  1189. runTimeError(INVALID_NCNAME_ERR,name);
  1190. }
  1191. }
  1192. /**
  1193. * Utility function to check if a name is a valid qname
  1194. * This method should only be invoked if the attribute value is an AVT
  1195. */
  1196. public static void checkQName(String name) {
  1197. if (!XMLChar.isValidQName(name)) {
  1198. runTimeError(INVALID_QNAME_ERR,name);
  1199. }
  1200. }
  1201. /**
  1202. * Utility function for the implementation of xsl:element.
  1203. */
  1204. public static String startXslElement(String qname, String namespace,
  1205. SerializationHandler handler, DOM dom, int node)
  1206. {
  1207. try {
  1208. // Get prefix from qname
  1209. String prefix;
  1210. final int index = qname.indexOf(':');
  1211. if (index > 0) {
  1212. prefix = qname.substring(0, index);
  1213. // Handle case when prefix is not known at compile time
  1214. if (namespace == null || namespace.length() == 0) {
  1215. try {
  1216. // not sure if this line of code ever works
  1217. namespace = dom.lookupNamespace(node, prefix);
  1218. }
  1219. catch(RuntimeException e) {
  1220. handler.flushPending(); // need to flush or else can't get namespacemappings
  1221. NamespaceMappings nm = handler.getNamespaceMappings();
  1222. namespace = nm.lookupNamespace(prefix);
  1223. if (namespace == null) {
  1224. runTimeError(NAMESPACE_PREFIX_ERR,prefix);
  1225. }
  1226. }
  1227. }
  1228. handler.startElement(namespace, qname.substring(index+1),
  1229. qname);
  1230. handler.namespaceAfterStartElement(prefix, namespace);
  1231. }
  1232. else {
  1233. // Need to generate a prefix?
  1234. if (namespace != null && namespace.length() > 0) {
  1235. prefix = generatePrefix();
  1236. qname = prefix + ':' + qname;
  1237. handler.startElement(namespace, qname, qname);
  1238. handler.namespaceAfterStartElement(prefix, namespace);
  1239. }
  1240. else {
  1241. handler.startElement(null, null, qname);
  1242. }
  1243. }
  1244. }
  1245. catch (SAXException e) {
  1246. throw new RuntimeException(e.getMessage());
  1247. }
  1248. return qname;
  1249. }
  1250. /**
  1251. * This function is used in the execution of xsl:element
  1252. */
  1253. public static String getPrefix(String qname) {
  1254. final int index = qname.indexOf(':');
  1255. return (index > 0) ? qname.substring(0, index) : null;
  1256. }
  1257. /**
  1258. * This function is used in the execution of xsl:element
  1259. */
  1260. private static int prefixIndex = 0; // not thread safe!!
  1261. public static String generatePrefix() {
  1262. return ("ns" + prefixIndex++);
  1263. }
  1264. public static final String RUN_TIME_INTERNAL_ERR =
  1265. "RUN_TIME_INTERNAL_ERR";
  1266. public static final String RUN_TIME_COPY_ERR =
  1267. "RUN_TIME_COPY_ERR";
  1268. public static final String DATA_CONVERSION_ERR =
  1269. "DATA_CONVERSION_ERR";
  1270. public static final String EXTERNAL_FUNC_ERR =
  1271. "EXTERNAL_FUNC_ERR";
  1272. public static final String EQUALITY_EXPR_ERR =
  1273. "EQUALITY_EXPR_ERR";
  1274. public static final String INVALID_ARGUMENT_ERR =
  1275. "INVALID_ARGUMENT_ERR";
  1276. public static final String FORMAT_NUMBER_ERR =
  1277. "FORMAT_NUMBER_ERR";
  1278. public static final String ITERATOR_CLONE_ERR =
  1279. "ITERATOR_CLONE_ERR";
  1280. public static final String AXIS_SUPPORT_ERR =
  1281. "AXIS_SUPPORT_ERR";
  1282. public static final String TYPED_AXIS_SUPPORT_ERR =
  1283. "TYPED_AXIS_SUPPORT_ERR";
  1284. public static final String STRAY_ATTRIBUTE_ERR =
  1285. "STRAY_ATTRIBUTE_ERR";
  1286. public static final String STRAY_NAMESPACE_ERR =
  1287. "STRAY_NAMESPACE_ERR";
  1288. public static final String NAMESPACE_PREFIX_ERR =
  1289. "NAMESPACE_PREFIX_ERR";
  1290. public static final String DOM_ADAPTER_INIT_ERR =
  1291. "DOM_ADAPTER_INIT_ERR";
  1292. public static final String PARSER_DTD_SUPPORT_ERR =
  1293. "PARSER_DTD_SUPPORT_ERR";
  1294. public static final String NAMESPACES_SUPPORT_ERR =
  1295. "NAMESPACES_SUPPORT_ERR";
  1296. public static final String CANT_RESOLVE_RELATIVE_URI_ERR =
  1297. "CANT_RESOLVE_RELATIVE_URI_ERR";
  1298. public static final String UNSUPPORTED_XSL_ERR =
  1299. "UNSUPPORTED_XSL_ERR";
  1300. public static final String UNSUPPORTED_EXT_ERR =
  1301. "UNSUPPORTED_EXT_ERR";
  1302. public static final String UNKNOWN_TRANSLET_VERSION_ERR =
  1303. "UNKNOWN_TRANSLET_VERSION_ERR";
  1304. public static final String INVALID_QNAME_ERR = "INVALID_QNAME_ERR";
  1305. public static final String INVALID_NCNAME_ERR = "INVALID_NCNAME_ERR";
  1306. // All error messages are localized and are stored in resource bundles.
  1307. protected static ResourceBundle m_bundle;
  1308. public final static String ERROR_MESSAGES_KEY = "error-messages";
  1309. static {
  1310. String resource = "com.sun.org.apache.xalan.internal.xsltc.runtime.ErrorMessages";
  1311. m_bundle = ResourceBundle.getBundle(resource);
  1312. }
  1313. /**
  1314. * Print a run-time error message.
  1315. */
  1316. public static void runTimeError(String code) {
  1317. throw new RuntimeException(m_bundle.getString(code));
  1318. }
  1319. public static void runTimeError(String code, Object[] args) {
  1320. final String message = MessageFormat.format(m_bundle.getString(code),
  1321. args);
  1322. throw new RuntimeException(message);
  1323. }
  1324. public static void runTimeError(String code, Object arg0) {
  1325. runTimeError(code, new Object[]{ arg0 } );
  1326. }
  1327. public static void runTimeError(String code, Object arg0, Object arg1) {
  1328. runTimeError(code, new Object[]{ arg0, arg1 } );
  1329. }
  1330. public static void consoleOutput(String msg) {
  1331. System.out.println(msg);
  1332. }
  1333. /**
  1334. * Replace a certain character in a string with a new substring.
  1335. */
  1336. public static String replace(String base, char ch, String str) {
  1337. return (base.indexOf(ch) < 0) ? base :
  1338. replace(base, String.valueOf(ch), new String[] { str });
  1339. }
  1340. public static String replace(String base, String delim, String[] str) {
  1341. final int len = base.length();
  1342. final StringBuffer result = new StringBuffer();
  1343. for (int i = 0; i < len; i++) {
  1344. final char ch = base.charAt(i);
  1345. final int k = delim.indexOf(ch);
  1346. if (k >= 0) {
  1347. result.append(str[k]);
  1348. }
  1349. else {
  1350. result.append(ch);
  1351. }
  1352. }
  1353. return result.toString();
  1354. }
  1355. /**
  1356. * Utility method to allow setting parameters of the form
  1357. * {namespaceuri}localName
  1358. * which get mapped to an instance variable in the class
  1359. * Hence a parameter of the form "{http://foo.bar}xyz"
  1360. * will be replaced with the corresponding values
  1361. * by the BasisLibrary's utility method mapQNametoJavaName
  1362. * and thus get mapped to legal java variable names
  1363. */
  1364. public static String mapQNameToJavaName (String base ) {
  1365. return replace(base, ".-:/{}?#%*",
  1366. new String[] { "$dot$", "$dash$" ,"$colon$", "$slash$",
  1367. "","$colon$","$ques$","$hash$","$per$",
  1368. "$aster$"});
  1369. }
  1370. //-- End utility functions
  1371. }