0001: /*
0002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
0003: *
0004: * This file is part of Resin(R) Open Source
0005: *
0006: * Each copy or derived work must preserve the copyright notice and this
0007: * notice unmodified.
0008: *
0009: * Resin Open Source is free software; you can redistribute it and/or modify
0010: * it under the terms of the GNU General Public License as published by
0011: * the Free Software Foundation; either version 2 of the License, or
0012: * (at your option) any later version.
0013: *
0014: * Resin Open Source is distributed in the hope that it will be useful,
0015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
0017: * of NON-INFRINGEMENT. See the GNU General Public License for more
0018: * details.
0019: *
0020: * You should have received a copy of the GNU General Public License
0021: * along with Resin Open Source; if not, write to the
0022: * Free SoftwareFoundation, Inc.
0023: * 59 Temple Place, Suite 330
0024: * Boston, MA 02111-1307 USA
0025: *
0026: * @author Scott Ferguson
0027: */
0028:
0029: package com.caucho.xsl;
0030:
0031: import com.caucho.java.JavaCompiler;
0032: import com.caucho.java.JavaWriter;
0033: import com.caucho.loader.DynamicClassLoader;
0034: import com.caucho.log.Log;
0035: import com.caucho.server.util.CauchoSystem;
0036: import com.caucho.util.CharBuffer;
0037: import com.caucho.util.IntArray;
0038: import com.caucho.util.IntMap;
0039: import com.caucho.vfs.Depend;
0040: import com.caucho.vfs.Path;
0041: import com.caucho.vfs.WriteStream;
0042: import com.caucho.xml.QAbstractNode;
0043: import com.caucho.xml.QAttr;
0044: import com.caucho.xml.QElement;
0045: import com.caucho.xml.QName;
0046: import com.caucho.xml.XmlChar;
0047: import com.caucho.xpath.Expr;
0048: import com.caucho.xpath.NamespaceContext;
0049: import com.caucho.xpath.expr.NumericExpr;
0050: import com.caucho.xpath.pattern.*;
0051: import com.caucho.xsl.fun.KeyFun;
0052: import com.caucho.xsl.java.*;
0053:
0054: import org.w3c.dom.*;
0055:
0056: import java.io.IOException;
0057: import java.text.DecimalFormatSymbols;
0058: import java.util.ArrayList;
0059: import java.util.HashMap;
0060: import java.util.Iterator;
0061: import java.util.Locale;
0062: import java.util.logging.Logger;
0063:
0064: /**
0065: * Generates code for a Java based stylesheet.
0066: *
0067: * <pre>
0068: * package work.xsl;
0069: * public class foo extends JavaStylesheet {
0070: * }
0071: * </pre>
0072: */
0073: public class JavaGenerator extends Generator {
0074: private static final Logger log = Log.open(JavaGenerator.class);
0075:
0076: private static HashMap<QName, Class> _tagMap;
0077: private static HashMap<QName, Class> _topTagMap;
0078:
0079: private static int _count;
0080:
0081: Path _path;
0082: WriteStream _s;
0083: JavaWriter _out;
0084:
0085: ArrayList<AbstractPattern> _matchPatterns = new ArrayList<AbstractPattern>();
0086: IntMap _matchMap = new IntMap();
0087: ArrayList<AbstractPattern> _selectPatterns = new ArrayList<AbstractPattern>();
0088: IntMap _selectMap = new IntMap();
0089:
0090: ArrayList<Expr> _exprs = new ArrayList<Expr>();
0091: IntMap _exprMap = new IntMap();
0092:
0093: ArrayList<Sort[]> _sorts = new ArrayList<Sort[]>();
0094: ArrayList<NamespaceContext> _namespaces = new ArrayList<NamespaceContext>();
0095: ArrayList<XslNumberFormat> _formats = new ArrayList<XslNumberFormat>();
0096: ArrayList<String> _functions = new ArrayList<String>();
0097: ArrayList<Template> _templateList = new ArrayList<Template>();
0098: ArrayList<String> _stylesheets = new ArrayList<String>();
0099: int _templateCount = 0;
0100: // integer counting unique identifier
0101: int _unique;
0102: HashMap<String, String> _macros = new HashMap<String, String>();
0103: ArrayList<Object> _fragments = new ArrayList<Object>();
0104:
0105: ArrayList<String> _strings = new ArrayList<String>();
0106: IntMap _stringMap = new IntMap();
0107:
0108: IntArray _envDepth = new IntArray();
0109:
0110: ArrayList<String> _modes = new ArrayList<String>();
0111:
0112: private XslNode _xslNode;
0113:
0114: private boolean _isLineBegin;
0115: private int _depth;
0116: private int _callDepth;
0117:
0118: // integer counting the depth of nested selects
0119: private int _selectDepth;
0120: private int _selectLoopDepth;
0121:
0122: private int _flagCount;
0123: private String _className;
0124: private String _pkg;
0125:
0126: private String _currentPos;
0127:
0128: private ClassLoader _parentLoader;
0129: private JavaCompiler _compiler;
0130: private boolean _disableEscaping;
0131: private boolean _printLocation = true;
0132:
0133: private String _oldFilename = null;
0134: private int _oldLine = -1;
0135:
0136: private boolean _hasHeader;
0137:
0138: /**
0139: * Creates a new XSL generator for Java.
0140: *
0141: * @param xslGenerator the owning factory.
0142: * @param className the name of the generated class
0143: * @param encoding the generated output encoding.
0144: */
0145: JavaGenerator(AbstractStylesheetFactory xslGenerator,
0146: String className, String encoding) throws IOException {
0147: super (xslGenerator);
0148:
0149: _parentLoader = xslGenerator.getClassLoader();
0150:
0151: ArrayList pathDepends = new ArrayList();
0152:
0153: _compiler = JavaCompiler.create(_parentLoader);
0154: _compiler.setClassDir(_workPath);
0155:
0156: if (encoding == null) {
0157: } else if (encoding.equalsIgnoreCase("UTF-16")) {
0158: // utf-16 isn't supported by some javac
0159: encoding = "UTF-8";
0160: _compiler.setEncoding(encoding);
0161: } else {
0162: _compiler.setEncoding(encoding);
0163: }
0164:
0165: int p = className.lastIndexOf('.');
0166: if (p >= 0) {
0167: _pkg = className.substring(0, p);
0168: className = className.substring(p + 1);
0169: } else {
0170: _pkg = "_xsl";
0171: className = className;
0172: }
0173:
0174: _className = className;
0175: init((_pkg + "." + className).replace('.', '/') + ".java");
0176:
0177: String fileName = (_pkg + "." + className).replace('.', '/')
0178: + ".java";
0179: _path = _workPath.lookup(fileName);
0180: _path.getParent().mkdirs();
0181:
0182: _s = _path.openWrite();
0183: if (encoding != null)
0184: _s.setEncoding(encoding);
0185: if (_s.getEncoding() == null
0186: || _s.getEncoding().equals("ISO-8859-1"))
0187: _s.setEncoding("JAVA");
0188: _out = new JavaWriter(_s);
0189: _out.setLineMap(_lineMap);
0190:
0191: _matchPatterns = new ArrayList<AbstractPattern>();
0192: _selectPatterns = new ArrayList<AbstractPattern>();
0193:
0194: _modes = new ArrayList<String>();
0195: _modes.add("");
0196: }
0197:
0198: protected JavaWriter getOut() {
0199: return _out;
0200: }
0201:
0202: public int getSelectDepth() {
0203: return _selectDepth;
0204: }
0205:
0206: public void setSelectDepth(int depth) {
0207: _selectDepth = depth;
0208: }
0209:
0210: public int pushSelectDepth() {
0211: return ++_selectDepth;
0212: }
0213:
0214: public int popSelectDepth() {
0215: return _selectDepth--;
0216: }
0217:
0218: public int getSelectLoopDepth() {
0219: return _selectLoopDepth;
0220: }
0221:
0222: public int pushSelectLoopDepth() {
0223: return ++_selectLoopDepth;
0224: }
0225:
0226: public int popSelectLoopDepth() {
0227: return _selectLoopDepth--;
0228: }
0229:
0230: public void setSelectLoopDepth(int depth) {
0231: _selectLoopDepth = depth;
0232: }
0233:
0234: public int generateId() {
0235: return _unique++;
0236: }
0237:
0238: public void clearUnique() {
0239: _unique = 0;
0240: }
0241:
0242: /**
0243: * Prints the generated header.
0244: */
0245: protected void printHeader() throws IOException {
0246: if (_hasHeader)
0247: return;
0248: _hasHeader = true;
0249:
0250: println("/*");
0251: println(" * Generated by " + com.caucho.Version.FULL_VERSION);
0252: println(" */");
0253: println();
0254: println("package " + _pkg + ";");
0255: println();
0256: println("import java.io.*;");
0257: println("import java.util.*;");
0258: println("import org.w3c.dom.*;");
0259: println("import org.xml.sax.*;");
0260: println("import com.caucho.util.*;");
0261: println("import com.caucho.xml.*;");
0262: println("import com.caucho.xpath.*;");
0263: println("import com.caucho.xpath.expr.*;");
0264: println("import com.caucho.xpath.pattern.*;");
0265: println("import com.caucho.xsl.*;");
0266:
0267: try {
0268: Class.forName("javax.servlet.Servlet");
0269: println("import javax.servlet.*;");
0270: println("import javax.servlet.jsp.*;");
0271: println("import javax.servlet.http.*;");
0272: } catch (Throwable e) {
0273: }
0274:
0275: for (int i = 0; i < _imports.size(); i++)
0276: println("import " + _imports.get(i) + ";");
0277: println();
0278:
0279: println("public class " + _className
0280: + " extends JavaStylesheet {");
0281: pushDepth();
0282:
0283: println("private StylesheetEnv stylesheets[];");
0284: }
0285:
0286: protected void generateChild(Node child) throws Exception {
0287: XslNode node = createChild(child);
0288:
0289: if (node != null)
0290: node.generate(_out);
0291: }
0292:
0293: protected XslNode createChild(XslNode parent, Node childNode)
0294: throws Exception {
0295: XslNode xslNode = _xslNode;
0296:
0297: _xslNode = parent;
0298:
0299: XslNode child = createChild(childNode);
0300:
0301: _xslNode = xslNode;
0302:
0303: return child;
0304: }
0305:
0306: protected XslNode createChild(Node child) throws Exception {
0307: XslNode xslNode = null;
0308:
0309: if (child instanceof QElement) {
0310: QElement elt = (QElement) child;
0311:
0312: Class cl = _tagMap.get(elt.getQName());
0313:
0314: if (cl != null) {
0315: xslNode = (XslNode) cl.newInstance();
0316: xslNode.setGenerator(this );
0317: xslNode.setParent(_xslNode);
0318:
0319: xslNode.setStartLocation(((QAbstractNode) child)
0320: .getBaseURI(), ((QAbstractNode) child)
0321: .getFilename(), ((QAbstractNode) child)
0322: .getLine());
0323:
0324: QAttr attr = (QAttr) elt.getFirstAttribute();
0325: for (; attr != null; attr = (QAttr) attr
0326: .getNextSibling()) {
0327: xslNode.addAttribute(attr.getQName(), attr
0328: .getNodeValue());
0329: }
0330:
0331: xslNode.endAttributes();
0332:
0333: XslNode oldNode = _xslNode;
0334: _xslNode = xslNode;
0335:
0336: Node node = elt.getFirstChild();
0337: for (; node != null; node = node.getNextSibling()) {
0338: XslNode xslChild = createChild(node);
0339:
0340: if (xslChild != null)
0341: xslNode.addChild(xslChild);
0342: }
0343:
0344: xslNode.endElement();
0345:
0346: _xslNode = oldNode;
0347: }
0348: /*
0349: else if (elt.getNodeName().equals("jsp:decl") ||
0350: elt.getNodeName().equals("jsp:declaration") ||
0351: elt.getNodeName().startsWith("jsp:directive")) {
0352: }
0353: */
0354: else if (child.getNodeName().startsWith("xsl:")
0355: && !XSLNS.equals(child.getNamespaceURI())) {
0356: throw error(
0357: child,
0358: L
0359: .l(
0360: "<{0}> has an xsl: prefix, but is not in the {1} namespace. XSL requires an xmlns:xsl=\"{1}\" namespace attribute.",
0361: child.getNodeName(), XSLNS));
0362: } else if (!XSLNS.equals(child.getNamespaceURI())
0363: && !XTPNS.equals(child.getNamespaceURI())) {
0364: xslNode = new XslElementNode(elt.getQName());
0365: xslNode.setGenerator(this );
0366: xslNode.setParent(_xslNode);
0367:
0368: xslNode.setStartLocation(((QAbstractNode) child)
0369: .getBaseURI(), ((QAbstractNode) child)
0370: .getFilename(), ((QAbstractNode) child)
0371: .getLine());
0372:
0373: QAttr attr = (QAttr) elt.getFirstAttribute();
0374: for (; attr != null; attr = (QAttr) attr
0375: .getNextSibling())
0376: xslNode.addAttribute(attr.getQName(), attr
0377: .getNodeValue());
0378:
0379: xslNode.endAttributes();
0380:
0381: XslNode oldNode = _xslNode;
0382: _xslNode = xslNode;
0383:
0384: Node node = elt.getFirstChild();
0385: for (; node != null; node = node.getNextSibling()) {
0386: XslNode xslChild = createChild(node);
0387:
0388: xslNode.addChild(xslChild);
0389: }
0390:
0391: xslNode.endElement();
0392:
0393: _xslNode = oldNode;
0394: } else {
0395: throw error(child, L.l("<{0}> is an unknown XSL tag.",
0396: child.getNodeName()));
0397: /*
0398: XslWrapperNode wrapNode = new XslWrapperNode();
0399: wrapNode.setNode(child);
0400: xslNode = wrapNode;
0401: xslNode.setGenerator(this);
0402: */
0403: }
0404: } else if (child instanceof Text) {
0405: xslNode = new TextNode(((Text) child).getData());
0406: xslNode.setGenerator(this );
0407: xslNode.setParent(_xslNode);
0408: } else if (child instanceof Comment) {
0409: } else if (child instanceof ProcessingInstruction) {
0410: } else
0411: throw new UnsupportedOperationException(String
0412: .valueOf(child));
0413:
0414: if (xslNode != null) {
0415: xslNode.setStartLocation(((QAbstractNode) child)
0416: .getBaseURI(), ((QAbstractNode) child)
0417: .getFilename(), ((QAbstractNode) child).getLine());
0418: }
0419:
0420: return xslNode;
0421: }
0422:
0423: /**
0424: * Generates code for a template
0425: *
0426: * @param absNode the XSL node for the emplace
0427: * @param name the template name
0428: * @param pattern the pattern string
0429: * @param mode the template's mode
0430: * @param priority the template's priority
0431: */
0432: protected void printTemplate(Element absNode, String name,
0433: String pattern, String mode, double priority)
0434: throws Exception {
0435: throw new RuntimeException();
0436: /*
0437: QElement node = (QElement) absNode;
0438:
0439: if (name != null && ! name.equals(""))
0440: addMacro(name, node);
0441:
0442: if (! pattern.equals("")) {
0443: String fun = createTemplatePattern(name, pattern,
0444: mode, priority);
0445:
0446: print("// '" + pattern.replace('\n', ' ') + "'");
0447:
0448: if (mode != null && mode != "") {
0449: if (! _modes.contains(mode))
0450: _modes.add(mode);
0451: println(" mode '" + mode + "'");
0452: }
0453: else
0454: println();
0455:
0456: printString("// " + node.getFilename() + ":" + node.getLine());
0457: println();
0458:
0459: println("private void " + fun +
0460: "(XslWriter out, Node inputNode, Env env)");
0461: println(" throws Exception");
0462: println("{");
0463: pushDepth();
0464:
0465: println("Object _xsl_tmp;");
0466: println("Node node = inputNode;");
0467: println("int _xsl_top = env.getTop();");
0468:
0469: if (_isRawText)
0470: println("boolean oldEscaping = out.disableEscaping(true);");
0471: else
0472: println("boolean oldEscaping = out.disableEscaping(false);");
0473:
0474: String filename = node.getBaseURI();
0475: if (filename != null) {
0476: int pos = _stylesheets.indexOf(filename);
0477: if (pos < 0) {
0478: pos = _stylesheets.size();
0479: _stylesheets.add(filename);
0480: }
0481:
0482: println("env.setStylesheetEnv(stylesheets[" + pos + "]);");
0483: }
0484:
0485: _selectDepth = 0;
0486: _unique = 0;
0487:
0488: if (node.getLocalName().equals("template") ||
0489: node.getLocalName().equals("xsl:template"))
0490: generateChildren(node);
0491: else
0492: generateChild((QAbstractNode) node);
0493:
0494: if (! _isCacheable)
0495: println("out.setNotCacheable();");
0496:
0497: println("out.disableEscaping(oldEscaping);");
0498: println("env.popToTop(_xsl_top);");
0499: popDepth();
0500: println("}");
0501: println();
0502: }
0503: */
0504: }
0505:
0506: public void addMacro(String name, String functionName) {
0507: _macros.put(name, functionName);
0508: }
0509:
0510: /*
0511: public void addMacro(String name)
0512: {
0513: addMacro(name, "_xsl_macro_" + toJavaIdentifier(name);
0514: }
0515: */
0516:
0517: public boolean hasMacro(String name) {
0518: return _macros.keySet().contains(name);
0519: }
0520:
0521: /**
0522: * Generates the pattern for a matching pattern
0523: *
0524: * @param name the mangled name of the function
0525: * @param match the XPath match pattern
0526: * @param mode the template mode
0527: * @param priority the template priority
0528: * @param node the source XML node from the XSL file
0529: *
0530: * @return the name of the function
0531: */
0532: public String createTemplatePattern(String name,
0533: AbstractPattern match, String mode, double priority)
0534: throws Exception {
0535: String tagName;
0536:
0537: if (name != null)
0538: tagName = getName(name);
0539: else
0540: tagName = getName(match.toString());
0541:
0542: String function = "_xsl_template_" + tagName;
0543: _functions.add(function);
0544:
0545: if (match != null) {
0546: Template template = addPattern(match, mode, priority,
0547: function, _functions.size());
0548: _templateList.add(template);
0549: } else
0550: _templateList.add(null);
0551:
0552: return function;
0553: }
0554:
0555: protected void startDisableEscaping() throws IOException {
0556: if (!_isRawText)
0557: println("out.disableEscaping(true);");
0558: }
0559:
0560: protected void endDisableEscaping() throws IOException {
0561: if (!_isRawText)
0562: println("out.disableEscaping(false);");
0563: }
0564:
0565: /**
0566: * Creates Java code to print plain text.
0567: */
0568: protected void writeText(String text) throws Exception {
0569: if (text == null || text.length() == 0)
0570: return;
0571:
0572: int index = _stringMap.get(text);
0573: if (index < 0) {
0574: index = _strings.size();
0575: _stringMap.put(text, index);
0576: _strings.add(text);
0577: }
0578:
0579: printLocation(_systemId, _filename, _line);
0580: println("out.write(_xsl_string" + index + ", 0, "
0581: + text.length() + ");");
0582: }
0583:
0584: protected void printElement(Node node) throws Exception {
0585: QElement elt = (QElement) node;
0586: String name = node.getNodeName();
0587:
0588: if (name.equals("jsp:decl") || name.equals("jsp:declaration")) {
0589: println("if (out.isFlagFirst(" + _flagCount++ + ")) {");
0590: pushDepth();
0591: }
0592:
0593: String prefix = elt.getPrefix();
0594: String local = elt.getLocalName();
0595: String namespace = elt.getNamespaceURI();
0596:
0597: String[] postPrefix = (String[]) _namespaceAliases
0598: .get(namespace);
0599: if (postPrefix != null) {
0600: prefix = postPrefix[0];
0601: namespace = postPrefix[1];
0602: if (prefix == null || prefix.equals(""))
0603: name = local;
0604: else
0605: name = prefix + ":" + local;
0606: }
0607: if (_excludedNamespaces.get(namespace) != null)
0608: namespace = null;
0609:
0610: printLocation(_systemId, _filename, _line);
0611: if (namespace == null || namespace.equals("")) {
0612: print("out.pushElement(");
0613: print(name == null ? "null" : ("\"" + name + "\""));
0614: println(");");
0615: } else {
0616: print("out.pushElement(");
0617: print(namespace == null ? "null"
0618: : ("\"" + namespace + "\""));
0619: print(prefix == null ? ", null" : (", \"" + prefix + "\""));
0620: print(local == null ? ", null" : (", \"" + local + "\""));
0621: print(name == null ? ", null" : (", \"" + name + "\""));
0622: println(");");
0623: }
0624:
0625: printUseAttributeSet((QElement) node, false);
0626:
0627: NamedNodeMap list = node.getAttributes();
0628: for (int i = 0; i < list.getLength(); i++) {
0629: QAbstractNode attr = (QAbstractNode) list.item(i);
0630:
0631: printAttribute(attr, elt);
0632: }
0633:
0634: generateChildren(node);
0635:
0636: println("out.popElement();");
0637:
0638: if (node.getNodeName().equals("jsp:decl")
0639: || node.getNodeName().equals("jsp:declaration")) {
0640: popDepth();
0641: println("}");
0642: }
0643: }
0644:
0645: /**
0646: * Prints a command to set the current file and line into the
0647: * generated document.
0648: *
0649: * @param filename the source filename
0650: * @param line the source line number.
0651: */
0652: public void printLocation(String systemId, String filename, int line)
0653: throws Exception {
0654: if (_printLocation && filename != null && !_isSpecial) {
0655: print("out.setLocation(");
0656: if (systemId != null) {
0657: print("\"");
0658: printString(systemId);
0659: print("\"");
0660: } else
0661: print("null");
0662: print(", \"");
0663: printString(filename);
0664: println("\", " + line + ");");
0665: _oldFilename = filename;
0666: _oldLine = line;
0667: }
0668: }
0669:
0670: /**
0671: * Prints code for an element's attributes.
0672: */
0673: private void printAttribute(QAbstractNode attr, QElement elt)
0674: throws Exception {
0675: if (attr.getNodeName().equals("xsl:use-attribute-sets")) {
0676: } else if (XSLNS.equals(elt.getNamespace(attr.getPrefix()))) {
0677: } else if (XTPNS.equals(elt.getNamespace(attr.getPrefix()))) {
0678: } else {
0679: QAbstractNode qnode = (QAbstractNode) attr;
0680: String prefix = qnode.getPrefix();
0681: String local = qnode.getLocalName();
0682: String namespace = qnode.getNamespaceURI();
0683: String value = attr.getNodeValue();
0684:
0685: String[] postSuffix = (String[]) _namespaceAliases
0686: .get(namespace);
0687: if (postSuffix != null) {
0688: prefix = postSuffix[0];
0689: namespace = postSuffix[1];
0690: }
0691:
0692: else if (value.equals(XSLNS) && prefix.equals("xmlns"))
0693: return;
0694: else if (value.equals(XTPNS) && prefix.equals("xmlns"))
0695: return;
0696:
0697: if (_excludedNamespaces.get(namespace) != null)
0698: namespace = null;
0699:
0700: if ("".equals(prefix)
0701: && ("".equals(namespace) || namespace == null)) {
0702: String var = generateStringVar(value, elt);
0703: println("out.setAttribute(\"" + local + "\", " + var
0704: + ");");
0705: } else {
0706: print("out.pushAttribute(");
0707: print(prefix == null ? "null" : ("\"" + prefix + "\""));
0708: print(local == null ? ", null"
0709: : (", \"" + local + "\""));
0710: print(namespace == null ? ", null" : (", \""
0711: + namespace + "\""));
0712: println(");");
0713: generateString(value, ',', elt);
0714: println("out.popAttribute();");
0715: }
0716: }
0717: }
0718:
0719: protected void pushCall() throws IOException {
0720: println("{");
0721: pushDepth();
0722: _callDepth++;
0723: println("Env _xsl_arg" + _callDepth
0724: + " = XPath.createCall(env);");
0725: }
0726:
0727: public int pushCallDepth() {
0728: return ++_callDepth;
0729: }
0730:
0731: public int popCallDepth() {
0732: return _callDepth--;
0733: }
0734:
0735: public int getCallDepth() {
0736: return _callDepth;
0737: }
0738:
0739: protected void popCall() throws IOException {
0740: //println("_xsl_arg" + callDepth + ".free();");
0741: _callDepth--;
0742: popDepth();
0743: println("}");
0744: }
0745:
0746: /**
0747: * Prints code for xsl:apply-templates
0748: *
0749: * @param select the select pattern
0750: * @param mode the template mode
0751: * @param sort the sort expressions
0752: */
0753: protected void printApplyTemplates(AbstractPattern select,
0754: String mode, Sort[] sort) throws Exception {
0755: int min = 0;
0756: int max = Integer.MAX_VALUE;
0757:
0758: String applyName = "applyNode" + getModeName(mode);
0759: String env = "_xsl_arg" + _callDepth;
0760:
0761: if (select == null && sort == null) {
0762: println("for (Node _xsl_node = node.getFirstChild();");
0763: println(" _xsl_node != null;");
0764: println(" _xsl_node = _xsl_node.getNextSibling()) {");
0765: println(" " + env + ".setSelect(node, null);");
0766: println(" " + env + ".setCurrentNode(_xsl_node);");
0767: println(" " + applyName + "(out, _xsl_node, " + env + ", "
0768: + min + ", " + max + ");");
0769: println("}");
0770: } else if (sort == null) {
0771: int oldSelectDepth = _selectDepth;
0772: println(env + ".setSelect(node, _select_patterns["
0773: + addSelect(select) + "]);");
0774:
0775: String name = printSelectBegin(select, false, null);
0776:
0777: println(env + ".setCurrentNode(" + name + ");");
0778:
0779: println(applyName + "(out, " + name + ", " + env + ", "
0780: + min + ", " + max + ");");
0781:
0782: for (; _selectDepth > oldSelectDepth; _selectDepth--) {
0783: popDepth();
0784: println("}");
0785: }
0786: } else {
0787: println("{");
0788: pushDepth();
0789: println("ArrayList _xsl_list = xslSort(node, env"
0790: + ", _select_patterns[" + addSelect(select) + "]"
0791: + ", _xsl_sorts[" + _sorts.size() + "]);");
0792: println(env + ".setContextSize(_xsl_list.size());");
0793: println("for (int _xsl_i = 0; _xsl_i < _xsl_list.size(); _xsl_i++) {");
0794: println(" " + env + ".setContextPosition(_xsl_i + 1);");
0795: println(" " + applyName
0796: + "(out, (Node) _xsl_list.get(_xsl_i)" + ", " + env
0797: + ", " + min + ", " + max + ");");
0798: println("}");
0799: popDepth();
0800: println("}");
0801:
0802: _sorts.add(sort);
0803: }
0804: }
0805:
0806: public int addSort(Sort[] sort) {
0807: int index = _sorts.size();
0808:
0809: _sorts.add(sort);
0810:
0811: return index;
0812: }
0813:
0814: /**
0815: * Prints code to implement xsl:apply-imports
0816: *
0817: * @param mode the mode of the imported files
0818: * @param min the min importance
0819: * @param max the max importance
0820: */
0821: protected void printApplyImports(String mode, int min, int max)
0822: throws Exception {
0823: }
0824:
0825: protected void printCallTemplate(String name, String mode)
0826: throws Exception {
0827: println(getMacroName(name) + "(out, node, _xsl_arg"
0828: + _callDepth + ");");
0829: }
0830:
0831: public String getMacroName(String name) {
0832: return _macros.get(name);
0833: //return "_xsl_macro_" + toJavaIdentifier(name);
0834: }
0835:
0836: /**
0837: * Prints the value for a parameter.
0838: */
0839: protected void printParam(String name, String value, Element elt)
0840: throws Exception {
0841: print("_xsl_arg" + _callDepth + ".addVar(\"" + name + "\", ");
0842: generateString(value, '+', elt);
0843: println(");");
0844: }
0845:
0846: protected void printParam(String name, Object value)
0847: throws Exception {
0848: if (value instanceof Expr) {
0849: print("_exprs[" + addExpr((Expr) value) + "]");
0850: println(".addVar(_xsl_arg" + _callDepth + ", \"" + name
0851: + "\", " + "node, env);");
0852: } else {
0853: print("_xsl_arg" + _callDepth + ".addVar(\"");
0854: print(name);
0855: print("\", ");
0856: printVariableValue(value);
0857: println(");");
0858: }
0859: }
0860:
0861: /**
0862: * Prints code to add the value of an expression as a parameter.
0863: */
0864: protected void printParamVariable(String name, Expr value)
0865: throws Exception {
0866: print("_exprs[" + addExpr(value) + "]");
0867: println(".addParam(env, \"" + name + "\", " + "node, env);");
0868: }
0869:
0870: protected void printParamVariable(String name, Element value)
0871: throws Exception {
0872: if (value.getFirstChild() != null) {
0873: println("_xsl_tmp = env.getVar(\"" + name + "\");");
0874: println("if (_xsl_tmp == null)");
0875: print(" _xsl_tmp = ");
0876: printVariableValue(value);
0877: println(";");
0878: println("env.addVar(\"" + name + "\", _xsl_tmp);");
0879: }
0880: }
0881:
0882: protected void printVariable(String name, Object value)
0883: throws Exception {
0884: if (value instanceof Expr) {
0885: print("_exprs[" + addExpr((Expr) value) + "]");
0886: println(".addVar(env, \"" + name + "\", node, env);");
0887: } else {
0888: print("env.addVar(\"");
0889: print(name);
0890: print("\", ");
0891: printVariableValue(value);
0892: println(");");
0893: }
0894: }
0895:
0896: protected void printAssign(String name, Object value)
0897: throws Exception {
0898: if (value instanceof Expr) {
0899: print("_exprs[" + addExpr((Expr) value) + "]");
0900: println(".setVar(\"" + name + "\", node, env, node);");
0901: } else {
0902: print("env.setVar(\"");
0903: print(name);
0904: print("\", ");
0905: printVariableValue(value);
0906: println(");");
0907: }
0908: }
0909:
0910: private void printVariableValue(Object value) throws Exception {
0911: if (value instanceof Expr) {
0912: print("_exprs[" + addExpr((Expr) value)
0913: + "].evalObject(node, env)");
0914: } else if (value instanceof Node) {
0915: print("_xsl_fragment" + _fragments.size()
0916: + "(out, node, env)");
0917: _fragments.add(value);
0918: } else
0919: throw new RuntimeException();
0920: }
0921:
0922: protected void printPopScope(int count) throws Exception {
0923: if (count > 0)
0924: println("env.popVars(" + count + ");");
0925: }
0926:
0927: protected void printCopyOf(String select, Element elt)
0928: throws Exception {
0929: println("out.copyOf(_exprs[ " + addExpr(select)
0930: + "].evalObject(node, env));");
0931: }
0932:
0933: protected void printSelectValue(String select, Element elt)
0934: throws Exception {
0935: printStringExpr(select, elt);
0936: }
0937:
0938: protected void printForEach(Element element, String select)
0939: throws Exception {
0940: println("{");
0941: pushDepth();
0942:
0943: AbstractPattern selectPattern = null;
0944: try {
0945: selectPattern = parseSelect(select);
0946: } catch (Exception e) {
0947: }
0948:
0949: boolean hasExprEnv = !allowJavaSelect(selectPattern);
0950:
0951: int id = _unique++;
0952:
0953: String sel = "_xsl_sel" + id;
0954: String oldCxt = "_xsl_cxt" + id;
0955: String oldCur = "_xsl_cur" + id;
0956: String oldSel = "_xsl_old_sel" + id;
0957: String oldEnv = "_xsl_env" + id;
0958:
0959: println("com.caucho.xpath.pattern.AbstractPattern " + sel + ";");
0960: print(sel + " = _select_patterns[");
0961: print(createNodeSet(select, element));
0962: println("];");
0963: println("Node " + oldCxt + " = env.getContextNode();");
0964: println("Node " + oldCur + " = env.getCurrentNode();");
0965:
0966: if (!hasExprEnv) {
0967: println("AbstractPattern " + oldSel
0968: + " = env.setSelect(node, " + sel + ");");
0969: }
0970:
0971: // String pos = "_xsl_pos" + unique++;
0972: String iter = "_xsl_iter" + _unique++;
0973:
0974: int oldSelectDepth = _selectDepth;
0975:
0976: // println("int " + pos + " = 0;");
0977:
0978: boolean hasEnv = false;
0979:
0980: if (allowJavaSelect(selectPattern)) {
0981: println("ExprEnvironment " + oldEnv
0982: + " = env.setExprEnv(null);");
0983:
0984: String ptr = printSelectBegin(selectPattern, true, null);
0985:
0986: pushLoop();
0987: println("Node " + getElement() + " = node;");
0988: println("node = " + ptr + ";");
0989: } else {
0990: print("NodeIterator " + iter + " = " + sel);
0991: println(".select(node, " + getEnv() + ");");
0992: println("ExprEnvironment " + oldEnv + " = env.setExprEnv("
0993: + iter + ");");
0994: println("while (" + iter + ".hasNext()) {");
0995: pushDepth();
0996: _selectDepth++;
0997:
0998: pushLoop();
0999:
1000: println("Node " + getElement() + " = node;");
1001: println("node = " + iter + ".nextNode();");
1002:
1003: }
1004: println("env.setCurrentNode(node);");
1005:
1006: // println(pos + "++;");
1007:
1008: // String oldPos = currentPos;
1009: // currentPos = pos;
1010:
1011: AbstractPattern oldNodeListContext = _nodeListContext;
1012: _nodeListContext = parseMatch(select);
1013:
1014: generateChildren(element);
1015:
1016: _nodeListContext = oldNodeListContext;
1017:
1018: // currentPos = oldPos;
1019:
1020: println("node = " + getElement() + ";");
1021: println("env.setCurrentNode(" + oldCur + ");");
1022:
1023: for (; _selectDepth > oldSelectDepth; _selectDepth--) {
1024: popDepth();
1025: println("}");
1026: }
1027:
1028: println("env.setExprEnv(" + oldEnv + ");");
1029:
1030: if (!hasExprEnv) {
1031: println("env.setSelect(" + oldCxt + ", " + oldSel + ");");
1032: //println("env.setCurrentNode(node);");
1033: }
1034:
1035: popDepth();
1036: println("}");
1037: popLoop();
1038: }
1039:
1040: /**
1041: * Prints code for xsl:for-each when the for-each has any xsl:sort.
1042: */
1043: protected void printForEach(Element element, String select,
1044: Sort[] sort) throws Exception {
1045: println("{");
1046: pushDepth();
1047: println("env.setCurrentNode(node);");
1048: String pos = "_xsl_pos" + _unique++;
1049: String list = "_xsl_list" + _unique++;
1050:
1051: println("ArrayList " + list + " = xslSort(node, env"
1052: + ", _select_patterns[" + addSelect(select) + "]"
1053: + ", _xsl_sorts[" + _sorts.size() + "]);");
1054: println("env.setContextSize(" + list + ".size());");
1055: println("for (int " + pos + " = 1; " + pos + " <= " + list
1056: + ".size(); " + pos + "++) {");
1057: pushLoop();
1058: pushDepth();
1059: println("Node " + getElement() + " = node;");
1060: println("node = (Node) " + list + ".get(" + pos + " - 1);");
1061:
1062: String oldPos = _currentPos;
1063: _currentPos = pos;
1064:
1065: println("env.setPosition(" + _currentPos + ");");
1066:
1067: _sorts.add(sort);
1068:
1069: AbstractPattern oldNodeListContext = _nodeListContext;
1070: _nodeListContext = parseMatch(select);
1071:
1072: generateChildren(element);
1073:
1074: _currentPos = oldPos;
1075:
1076: _nodeListContext = oldNodeListContext;
1077:
1078: println("node = " + getElement() + ";");
1079:
1080: popDepth();
1081: println("}");
1082: popLoop();
1083: popDepth();
1084: println("}");
1085: }
1086:
1087: public String getCurrentPosition() {
1088: return _currentPos;
1089: }
1090:
1091: public void setCurrentPosition(String pos) {
1092: _currentPos = pos;
1093: }
1094:
1095: public AbstractPattern getNodeListContext() {
1096: return _nodeListContext;
1097: }
1098:
1099: public void setNodeListContext(AbstractPattern context) {
1100: _nodeListContext = context;
1101: }
1102:
1103: protected void printIf(Element element, Expr test) throws Exception {
1104: print("if (");
1105: printExprTest(test, "node");
1106: println(") {");
1107: pushDepth();
1108: generateChildren(element);
1109: popDepth();
1110: println("}");
1111: }
1112:
1113: protected void printChoose(Element element, Expr expr, boolean first)
1114: throws Exception {
1115: if (!first)
1116: print("else if (");
1117: else
1118: print("if (");
1119: printExprTest(expr, "node");
1120: println(") {");
1121: pushDepth();
1122: generateChildren(element);
1123: popDepth();
1124: println("}");
1125: }
1126:
1127: protected void printOtherwise(Element element, boolean first)
1128: throws Exception {
1129: if (!first)
1130: print("else ");
1131: println("{");
1132: pushDepth();
1133: generateChildren(element);
1134: popDepth();
1135: println("}");
1136: }
1137:
1138: void printNumber(Expr expr, XslNumberFormat format)
1139: throws Exception {
1140: print("exprNumber(out, node, env, _exprs[" + addExpr(expr)
1141: + "]");
1142: print(", _xsl_formats[" + _formats.size() + "]");
1143: println(");");
1144:
1145: _formats.add(format);
1146: }
1147:
1148: void printNumber(String level, AbstractPattern countPattern,
1149: AbstractPattern fromPattern, XslNumberFormat format)
1150: throws Exception {
1151: if (level.equals("single"))
1152: print("singleNumber(out, ");
1153: else if (level.equals("multiple"))
1154: print("multiNumber(out, ");
1155: else if (level.equals("any"))
1156: print("anyNumber(out, ");
1157: else
1158: throw error("xsl:number cannot understand level=`" + level
1159: + "'");
1160:
1161: print("node, env, ");
1162: printPattern(countPattern);
1163: print(", ");
1164: printPattern(fromPattern);
1165: print(", _xsl_formats[" + _formats.size() + "]");
1166: println(");");
1167:
1168: _formats.add(format);
1169: }
1170:
1171: public int addFormat(XslNumberFormat format) {
1172: int index = _formats.size();
1173:
1174: _formats.add(format);
1175:
1176: return index;
1177: }
1178:
1179: protected void printCopy(Element element) throws Exception {
1180: println("out.pushCopy(node);");
1181: printUseAttributeSet(element, true);
1182: generateChildren(element);
1183: println("out.popCopy(node);");
1184: }
1185:
1186: protected void printResultDocument(Element element, String href,
1187: String format) throws Exception {
1188: println("XslWriter oldOut = out;");
1189: println("OutputStream os = null;");
1190: println("try {");
1191: pushDepth();
1192: print("os = out.openWrite(env, ");
1193: generateString(href, '+', element);
1194: println(");");
1195:
1196: println("out = out.openResultDocument(os);");
1197: generateChildren(element);
1198: println("out.close();");
1199: popDepth();
1200: println("} finally {");
1201: println(" if (os != null)");
1202: println(" os.close();");
1203: println(" out = oldOut;");
1204: println("}");
1205: }
1206:
1207: protected void printElement(Element element, String name)
1208: throws Exception {
1209: print("out.pushElement(");
1210: generateString(name, '+', element);
1211: if (_namespace != null) {
1212: print(", ");
1213: printNamespace(_namespace);
1214: }
1215: println(");");
1216: printUseAttributeSet(element, true);
1217: generateChildren(element);
1218: println("out.popElement();");
1219: }
1220:
1221: protected void printElement(Element element, String name,
1222: String namespace) throws Exception {
1223: print("out.pushElementNs(");
1224: generateString(name, '+', element);
1225: print(", ");
1226: generateString(namespace, '+', element);
1227: println(");");
1228: printUseAttributeSet(element, true);
1229: generateChildren(element);
1230: print("out.popElement();");
1231: }
1232:
1233: /**
1234: * Prints the attributes in a use-attribute-set.
1235: */
1236: private void printUseAttributeSet(Element element, boolean isXSL)
1237: throws Exception {
1238: Attr attr = (Attr) ((QElement) element).getFirstAttribute();
1239: for (; attr != null; attr = (Attr) attr.getNextSibling()) {
1240: if (isXSL
1241: && attr.getNodeName().equals("use-attribute-sets")
1242: || !isXSL
1243: && attr.getNodeName().equals(
1244: "xsl:use-attribute-sets")) {
1245: HashMap set = getAttributeSet(attr.getNodeValue());
1246: if (set == null)
1247: continue;
1248: Iterator iter = set.keySet().iterator();
1249: while (iter.hasNext()) {
1250: String key = (String) iter.next();
1251: String value = (String) set.get(key);
1252:
1253: printAttributeValue(key, value, element);
1254: }
1255: }
1256: }
1257: }
1258:
1259: /**
1260: * Returns the named attribute set.
1261: */
1262: public HashMap<String, String> getAttributeSet(String name) {
1263: CharBuffer cb = CharBuffer.allocate();
1264: int i = 0;
1265: int len = name.length();
1266:
1267: HashMap<String, String> map = new HashMap<String, String>();
1268:
1269: while (i < len) {
1270: for (; i < len && name.charAt(i) == ' '; i++) {
1271: }
1272:
1273: cb.clear();
1274: for (; i < len && name.charAt(i) != ' '; i++)
1275: cb.append(name.charAt(i));
1276:
1277: if (cb.length() > 0) {
1278: XslAttributeSet newSet = _attributeSets.get(cb
1279: .toString());
1280:
1281: if (newSet != null) {
1282: ArrayList<XslAttribute> attrList = newSet
1283: .getAttributes();
1284:
1285: for (int j = 0; j < attrList.size(); j++) {
1286: XslAttribute attr = attrList.get(j);
1287:
1288: map.put(attr.getName(), attr.getValue());
1289: }
1290: }
1291: }
1292: }
1293:
1294: return map;
1295: }
1296:
1297: /**
1298: * Returns the named attribute set.
1299: */
1300: public ArrayList<XslAttribute> getAttributeSetList(String name) {
1301: CharBuffer cb = CharBuffer.allocate();
1302: int i = 0;
1303: int len = name.length();
1304:
1305: ArrayList<XslAttribute> set = new ArrayList<XslAttribute>();
1306:
1307: while (i < len) {
1308: for (; i < len && name.charAt(i) == ' '; i++) {
1309: }
1310:
1311: cb.clear();
1312: for (; i < len && name.charAt(i) != ' '; i++)
1313: cb.append(name.charAt(i));
1314:
1315: if (cb.length() > 0) {
1316: XslAttributeSet newSet = _attributeSets.get(cb
1317: .toString());
1318:
1319: if (newSet != null) {
1320: set.addAll(newSet.getAttributes());
1321: }
1322: }
1323: }
1324:
1325: return set;
1326: }
1327:
1328: /**
1329: * Prints an xsl:attribute
1330: */
1331: protected void printAttribute(Element element, String name)
1332: throws Exception {
1333: print("out.pushAttribute(");
1334: generateString(name, '+', element);
1335:
1336: if (_namespace != null) {
1337: print(", ");
1338: printNamespace(_namespace);
1339: }
1340:
1341: println(");");
1342:
1343: generateChildren(element);
1344: println("out.popAttribute();");
1345: }
1346:
1347: /**
1348: * Prints a single attribute value.
1349: */
1350: private void printAttributeValue(String key, String value,
1351: Element elt) throws Exception {
1352: if (_namespace == null && !attributeHasSpecial(key)
1353: && !attributeHasSpecial(value)) {
1354: print("out.setAttribute(");
1355: generateString(key, '+', elt);
1356: print(", ");
1357: generateString(value, '+', elt);
1358: println(");");
1359: } else {
1360: print("out.pushAttribute(");
1361: generateString(key, '+', elt);
1362: if (_namespace != null) {
1363: print(", ");
1364: printNamespace(_namespace);
1365: }
1366: println(");");
1367: generateString(value, ',', elt);
1368: println("out.popAttribute();");
1369: }
1370: }
1371:
1372: public void printNamespace(NamespaceContext namespace)
1373: throws Exception {
1374: for (int i = 0; i < _namespaces.size(); i++) {
1375: if (_namespaces.get(i).equals(namespace)) {
1376: print("_namespaces[" + i + "]");
1377: return;
1378: }
1379: }
1380:
1381: print("_namespaces[" + _namespaces.size() + "]");
1382: _namespaces.add(namespace);
1383: }
1384:
1385: public int addNamespace(NamespaceContext namespace)
1386: throws Exception {
1387: for (int i = 0; i < _namespaces.size(); i++) {
1388: if (_namespaces.get(i).equals(namespace)) {
1389: return i;
1390: }
1391: }
1392:
1393: _namespaces.add(namespace);
1394:
1395: return _namespaces.size() - 1;
1396: }
1397:
1398: protected void printAttribute(Element element, String name,
1399: String namespace) throws Exception {
1400: print("out.pushAttributeNs(");
1401: generateString(name, '+', element);
1402: print(", ");
1403: generateString(namespace, '+', element);
1404: println(");");
1405: generateChildren(element);
1406: println("out.popAttribute();");
1407: }
1408:
1409: protected void printPi(Element element) throws Exception {
1410: String name = element.getAttribute("name");
1411: if (name.equals(""))
1412: throw error("xsl:pi expected `name' attribute.");
1413:
1414: print("out.pushPi();");
1415:
1416: generateChildren(element);
1417: println("out.popPi(");
1418: generateString(name, '+', element);
1419: println(");");
1420: }
1421:
1422: protected void printComment(Element element) throws Exception {
1423: println("out.pushComment();");
1424: generateChildren(element);
1425: println("out.popComment();");
1426: }
1427:
1428: protected void printError(String msg) throws Exception {
1429: println("if (true) throw new javax.xml.transform.TransformerException(\""
1430: + msg + "\");");
1431: }
1432:
1433: protected void printMessage(Element msg) throws Exception {
1434: int unique = _unique++;
1435:
1436: println("XMLWriter frag" + unique + " = out.pushFragment();");
1437: generateChildren(msg);
1438:
1439: String terminate = msg.getAttribute("terminate");
1440: if (terminate.equals("yes"))
1441: println("if (true) throw new javax.xml.transform.TransformerException(((QAbstractNode) out.popFragment(frag"
1442: + unique + ")).getTextValue());");
1443: else
1444: println("System.err.println(((QAbstractNode) out.popFragment(frag"
1445: + unique + ")).getTextValue());");
1446: }
1447:
1448: /**
1449: * Prints code to implement the xtp:expression tag, i.e. print
1450: * the value of the Java expression.
1451: */
1452: protected void printExpression(Element element) throws Exception {
1453: String expr = element.getAttribute("expr");
1454:
1455: if (!expr.equals("")) {
1456: print("out.print(");
1457: print(expr);
1458: println(");");
1459: } else {
1460: print("out.print(");
1461: print(((QAbstractNode) element).getTextValue());
1462: println(");");
1463: }
1464: }
1465:
1466: protected void printScriptlet(Element element) throws Exception {
1467: println(((QAbstractNode) element).getTextValue());
1468: }
1469:
1470: protected void printWhile(Element element, Expr test)
1471: throws Exception {
1472: print("while (");
1473: printExprTest(test, "node");
1474: println(") {");
1475: pushDepth();
1476: generateChildren(element);
1477: popDepth();
1478: println("}");
1479: }
1480:
1481: protected void printDeclaration(Element element) throws Exception {
1482: println(((QAbstractNode) element).getTextValue());
1483: }
1484:
1485: protected void printCacheDepends(String name) throws Exception {
1486: print("out.addCacheDepend(((com.caucho.vfs.Path) out.getProperty(\"caucho.pwd\")).lookup(\"");
1487: printString(name);
1488: println("\"));");
1489: }
1490:
1491: public String getElement() {
1492: return "node" + _loopDepth;
1493: }
1494:
1495: public void pushLoop() {
1496: _loopDepth++;
1497: }
1498:
1499: public void popLoop() {
1500: _loopDepth--;
1501: }
1502:
1503: public String getEnv() {
1504: return "env";
1505: }
1506:
1507: void pushEnv() {
1508: _envDepth.add(0);
1509: }
1510:
1511: void popEnv() {
1512: _envDepth.pop();
1513: }
1514:
1515: void printPattern(AbstractPattern pattern) throws Exception {
1516: if (pattern == null)
1517: print("null");
1518: else {
1519: print("_match_patterns[" + _matchPatterns.size() + "]");
1520: _matchPatterns.add(pattern);
1521: }
1522: }
1523:
1524: private int createNodeSet(String select, Element element)
1525: throws Exception {
1526: return addSelect(select);
1527: }
1528:
1529: int createSelectPattern(AbstractPattern pattern) throws Exception {
1530: return addSelect(pattern);
1531: }
1532:
1533: int createMatchPattern(String select, Element element)
1534: throws Exception {
1535: AbstractPattern pattern = parseMatch(select);
1536:
1537: _matchPatterns.add(pattern);
1538:
1539: return _matchPatterns.size() - 1;
1540: }
1541:
1542: String getName(String tag) {
1543: CharBuffer newTag = new CharBuffer();
1544:
1545: for (int i = 0; i < tag.length(); i++) {
1546: int ch = tag.charAt(i);
1547: switch (ch) {
1548: case ' ':
1549: case '\t':
1550: case '\r':
1551: case '\n':
1552: case '(':
1553: case ')':
1554: break;
1555:
1556: case ':':
1557: case '.':
1558: case '|':
1559: newTag.append('_');
1560: break;
1561:
1562: default:
1563: if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z'
1564: || ch >= '0' && ch <= '9')
1565: newTag.append((char) ch);
1566: }
1567: }
1568: tag = newTag.toString();
1569:
1570: if (_names.get(tag) == null) {
1571: _names.put(tag, tag);
1572: return tag;
1573: }
1574:
1575: int i = 0;
1576: while (true) {
1577: String subname = tag + i;
1578: if (_names.get(subname) == null) {
1579: _names.put(subname, subname);
1580: return subname;
1581: }
1582:
1583: i++;
1584: }
1585: }
1586:
1587: void printExprTest(Expr expr, String element) throws Exception {
1588: print("_exprs[" + addExpr(expr) + "].evalBoolean(" + element
1589: + ", " + getEnv() + ")");
1590: }
1591:
1592: public void printExprTest(int exprId, String element)
1593: throws Exception {
1594: print("_exprs[" + exprId + "].evalBoolean(" + element + ", "
1595: + getEnv() + ")");
1596: }
1597:
1598: private boolean attributeHasSpecial(String string) {
1599: int length = string.length();
1600:
1601: for (int i = 0; i < length; i++) {
1602: char ch = string.charAt(i);
1603:
1604: if (ch == '{' && i + 1 < length) {
1605: // {{ is treated as a single {
1606: if (string.charAt(i + 1) == '{') {
1607: i++;
1608: continue;
1609: }
1610:
1611: return true;
1612: }
1613: // <#= interpolates
1614: else if (i + 2 < length && ch == '<'
1615: && string.charAt(i + 1) == '#'
1616: && string.charAt(i + 2) == '=')
1617: return true;
1618: }
1619:
1620: return false;
1621: }
1622:
1623: /**
1624: * Produces code to generate an attribute value template. The same
1625: * code is used to produce a string ('a{b}c' -> "a" + b + "c") or a series of
1626: * print statements (',').
1627: *
1628: * @param string the source template
1629: * @param mode separator: either '+' or ','
1630: * @param elt the containing element. Needed for namespaces.
1631: */
1632: void generateString(String string, int mode, Element elt)
1633: throws Exception {
1634: CharBuffer cb = new CharBuffer();
1635: int i = 0;
1636: boolean first = true;
1637: int length = string.length();
1638:
1639: for (; i < length; i++) {
1640: char ch = string.charAt(i);
1641:
1642: if (ch == '\n') {
1643: cb.append("\\n");
1644: } else if (ch == '"') {
1645: cb.append("\\\"");
1646: } else if (ch == '{' && i + 1 < length) {
1647: // {{ is treated as a single {
1648: if (string.charAt(i + 1) == '{') {
1649: cb.append('{');
1650: i++;
1651: }
1652: // the value is computed from an XPath expr
1653: else {
1654: // print the gathered text if any
1655: if (mode == ',') {
1656: if (cb.length() > 0)
1657: println("out.print(\"" + cb.toString()
1658: + "\");");
1659: } else {
1660: if (!first)
1661: print((char) mode);
1662:
1663: if (cb.length() > 0) {
1664: print("\"");
1665: print(cb.toString());
1666: print("\"");
1667: print((char) mode);
1668: }
1669: }
1670:
1671: // scan the contents of '{' ... '}'
1672: cb.clear();
1673: for (i++; i < length && string.charAt(i) != '}'; i++)
1674: cb.append(string.charAt(i));
1675:
1676: // and add the results
1677: if (mode == ',')
1678: printStringExpr(cb.toString(), elt);
1679: else
1680: stringExpr(cb.toString(), elt);
1681: cb.clear();
1682: first = false;
1683: }
1684: }
1685: // }} is treated as a single }
1686: else if (ch == '}' && i + 1 < length) {
1687: if (string.charAt(i + 1) == '}') {
1688: cb.append('}');
1689: i++;
1690: } else
1691: cb.append('}');
1692: }
1693: // <#= interpolates
1694: else if (i + 2 < length && ch == '<'
1695: && string.charAt(i + 1) == '#'
1696: && string.charAt(i + 2) == '=') {
1697: // print the gathered text if any
1698: if (mode == ',') {
1699: if (cb.length() > 0)
1700: println("out.print(\"" + cb.toString() + "\");");
1701: } else {
1702: if (!first)
1703: print((char) mode);
1704:
1705: if (cb.length() > 0) {
1706: print("\"");
1707: print(cb.toString());
1708: print("\"");
1709: print((char) mode);
1710: }
1711: }
1712:
1713: // scan the contents of '{' ... '}'
1714: cb.clear();
1715: for (i += 3; i + 1 < length && string.charAt(i) != '#'
1716: && string.charAt(i + 1) != '>'; i++)
1717: cb.append(string.charAt(i));
1718:
1719: i++;
1720:
1721: // and add the results
1722: if (mode == ',')
1723: println("out.print(" + cb + ");");
1724: else {
1725: print("(" + cb + ")");
1726: }
1727: cb.clear();
1728: first = false;
1729: } else
1730: cb.append((char) ch);
1731: }
1732:
1733: // add any trailing text
1734: if (cb.length() > 0) {
1735: if (mode == ',')
1736: println("out.print(\"" + cb + "\");");
1737: else {
1738: if (!first)
1739: print((char) mode);
1740:
1741: print("\"" + cb + "\"");
1742: }
1743: } else if (first && mode == '+')
1744: print("\"\"");
1745: }
1746:
1747: /**
1748: * Produces code to generate an attribute value template. The same
1749: * code is used to produce a string ('a{b}c' -> "a" + b + "c") or a series of
1750: * print statements (',').
1751: *
1752: * @param string the source template
1753: * @param elt the containing element. Needed for namespaces.
1754: *
1755: * @return the variable storing the generated string.
1756: */
1757: String generateStringVar(String string, Element elt)
1758: throws Exception {
1759: CharBuffer cb = new CharBuffer();
1760: int i = 0;
1761: boolean first = true;
1762: int length = string.length();
1763:
1764: String strVar = "_xsl_str" + _unique++;
1765:
1766: if (string.indexOf('{') < 0 && string.indexOf('}') < 0) {
1767: print("String " + strVar + " = \"");
1768: printString(string);
1769: println("\";");
1770:
1771: return strVar;
1772: } else if (string.lastIndexOf('{') == 0
1773: && string.indexOf('}') == string.length() - 1) {
1774: println("String " + strVar + " = \"\";");
1775: string = string.substring(1, string.length() - 1);
1776:
1777: addStringExpr(strVar, string, elt, true);
1778: return strVar;
1779: }
1780:
1781: String cbVar = "_xsl_cb" + _unique++;
1782:
1783: println("com.caucho.util.CharBuffer " + cbVar
1784: + " = com.caucho.util.CharBuffer.allocate();");
1785:
1786: for (; i < length; i++) {
1787: char ch = string.charAt(i);
1788:
1789: if (ch == '\n') {
1790: cb.append("\\n");
1791: } else if (ch == '"') {
1792: cb.append("\\\"");
1793: } else if (ch == '{' && i + 1 < length) {
1794: // {{ is treated as a single {
1795: if (string.charAt(i + 1) == '{') {
1796: cb.append('{');
1797: i++;
1798: }
1799: // the value is computed from an XPath expr
1800: else {
1801: // print the gathered text if any
1802: if (cb.length() > 0)
1803: println(cbVar + ".append(\"" + cb.toString()
1804: + "\");");
1805:
1806: // scan the contents of '{' ... '}'
1807: cb.clear();
1808: for (i++; i < length && string.charAt(i) != '}'; i++)
1809: cb.append(string.charAt(i));
1810:
1811: // and add the results
1812: addStringExpr(cbVar, cb.toString(), elt, false);
1813:
1814: cb.clear();
1815: first = false;
1816: }
1817: }
1818: // }} is treated as a single }
1819: else if (ch == '}' && i + 1 < length) {
1820: if (string.charAt(i + 1) == '}') {
1821: cb.append('}');
1822: i++;
1823: } else
1824: cb.append('}');
1825: }
1826: // <#= interpolates
1827: else if (i + 2 < length && ch == '<'
1828: && string.charAt(i + 1) == '#'
1829: && string.charAt(i + 2) == '=') {
1830: // print the gathered text if any
1831: if (cb.length() > 0)
1832: println(cbVar + ".append(\"" + cb.toString()
1833: + "\");");
1834:
1835: // scan the contents of '<#=' ... '#>'
1836: cb.clear();
1837: for (i += 3; i + 1 < length && string.charAt(i) != '#'
1838: && string.charAt(i + 1) != '>'; i++)
1839: cb.append(string.charAt(i));
1840:
1841: i++;
1842:
1843: // and add the results
1844: println(cbVar + ".append(" + cb + ");");
1845: cb.clear();
1846: first = false;
1847: } else
1848: cb.append((char) ch);
1849: }
1850:
1851: // add any trailing text
1852: if (cb.length() > 0)
1853: println(cbVar + ".append(\"" + cb + "\");");
1854:
1855: println("String " + strVar + " = " + cbVar + ".close();");
1856:
1857: return strVar;
1858:
1859: }
1860:
1861: /**
1862: * Prints a value-of expression
1863: */
1864: private void printStringExpr(String exprString, Element elt)
1865: throws Exception {
1866: int length = exprString.length();
1867:
1868: if (length == 0)
1869: return;
1870:
1871: AbstractPattern select = null;
1872: try {
1873: select = parseSelect(exprString);
1874: } catch (Exception e) {
1875: }
1876:
1877: if (exprString.equals(".")) {
1878: println("out.valueOf(node);");
1879: return;
1880: } else if (exprString.charAt(0) == '@') {
1881: boolean isSimple = true;
1882:
1883: for (int i = 1; i < length; i++) {
1884: char ch = exprString.charAt(i);
1885: if (!XmlChar.isNameChar(ch) || ch == ':')
1886: isSimple = false;
1887: }
1888:
1889: if (isSimple) {
1890: println("if (node instanceof Element)");
1891: print(" out.print(((Element) node).getAttribute(\"");
1892: print(exprString.substring(1));
1893: println("\"));");
1894: return;
1895: }
1896: } else if (allowJavaSelect(select)) {
1897: int oldSelectDepth = _selectDepth;
1898:
1899: String loop = "_xsl_loop" + _unique++;
1900: _selectLoopDepth = 0;
1901:
1902: String ptr = printSelectBegin(select, true, loop);
1903:
1904: println("out.valueOf(" + ptr + ");");
1905: println("break " + loop + ";");
1906:
1907: for (; _selectDepth > oldSelectDepth; _selectDepth--) {
1908: popDepth();
1909: println("}");
1910: }
1911:
1912: return;
1913: }
1914:
1915: println("out.valueOf(_exprs[" + addExpr(exprString)
1916: + "].evalObject(node, " + getEnv() + "));");
1917: }
1918:
1919: /**
1920: * Prints a value-of expression
1921: */
1922: private void addStringExpr(String var, String exprString,
1923: Element elt, boolean isSingleString) throws Exception {
1924: int length = exprString.length();
1925:
1926: if (length == 0)
1927: return;
1928:
1929: AbstractPattern select = null;
1930: try {
1931: select = parseSelect(exprString);
1932: } catch (Exception e) {
1933: }
1934:
1935: if (exprString.equals(".")) {
1936: if (isSingleString)
1937: println(var + " = XmlUtil.textValue(node);");
1938: else
1939: println("XmlUtil.textValue(" + var + ", node);");
1940: return;
1941: } else if (exprString.charAt(0) == '@') {
1942: boolean isSimple = true;
1943:
1944: for (int i = 1; i < length; i++) {
1945: char ch = exprString.charAt(i);
1946: if (!XmlChar.isNameChar(ch) || ch == ':')
1947: isSimple = false;
1948: }
1949:
1950: if (isSimple) {
1951: println("if (node instanceof Element)");
1952: if (isSingleString) {
1953: print(" " + var
1954: + " = ((Element) node).getAttribute(\"");
1955: print(exprString.substring(1));
1956: println("\");");
1957: } else {
1958: print(" "
1959: + var
1960: + ".append(((Element) node).getAttribute(\"");
1961: print(exprString.substring(1));
1962: println("\"));");
1963: }
1964: return;
1965: }
1966: } else if (allowJavaSelect(select)) {
1967: int oldSelectDepth = _selectDepth;
1968:
1969: String loopVar = "_xsl_loop" + _unique++;
1970: _selectLoopDepth = 0;
1971:
1972: String ptr = printSelectBegin(select, true, loopVar);
1973:
1974: if (isSingleString)
1975: println(var + " = XmlUtil.textValue(" + ptr + ");");
1976: else
1977: println("XmlUtil.textValue(" + var + ", " + ptr + ");");
1978: println("break " + loopVar + ";");
1979:
1980: for (; _selectDepth > oldSelectDepth; _selectDepth--) {
1981: popDepth();
1982: println("}");
1983: }
1984:
1985: return;
1986: }
1987:
1988: if (isSingleString) {
1989: println(var + " = _exprs[" + addExpr(exprString)
1990: + "].evalString(node, " + getEnv() + ");");
1991: } else {
1992: println("_exprs[" + addExpr(exprString) + "].evalString("
1993: + var + ", node, " + getEnv() + ");");
1994: }
1995: }
1996:
1997: /**
1998: * Prints iterator code to start a select.
1999: */
2000: private String printSelectBegin(AbstractPattern select,
2001: boolean isForEach, String loopVar) throws IOException,
2002: XslParseException {
2003: if (select == null)
2004: throw new NullPointerException();
2005:
2006: if (select instanceof FromContext
2007: && ((FromContext) select).getCount() == 0)
2008: return "node";
2009:
2010: else if (select instanceof FromRoot)
2011: return "ownerDocument(node)";
2012:
2013: boolean useXPath = allowJavaSelect(select);
2014:
2015: String name = "node";
2016:
2017: if (!useXPath) {
2018: // punt and let XPath handle it.
2019: String iterName = "_xsl_iter" + _unique++;
2020:
2021: String ptrName = "_xsl_ptr" + _unique++;
2022:
2023: if (isForEach)
2024: println("env.setCurrentNode(node);");
2025: println("Iterator " + iterName + " = _select_patterns["
2026: + addSelect(select) + "].select(" + name
2027: + ", env);");
2028:
2029: if (loopVar != null && _selectLoopDepth == 0)
2030: println(loopVar + ":");
2031:
2032: println("while (" + iterName + ".hasNext()) {");
2033: pushDepth();
2034: _selectDepth++;
2035: _selectLoopDepth++;
2036: println("Node " + ptrName + " = (Node) " + iterName
2037: + ".next();");
2038:
2039: return ptrName;
2040: }
2041:
2042: if (select instanceof FromChildren) {
2043: name = printSelectBegin(select.getParent(), isForEach,
2044: loopVar);
2045:
2046: String ptrName = "_xsl_ptr" + _unique++;
2047:
2048: if (loopVar != null && _selectLoopDepth == 0)
2049: println(loopVar + ":");
2050:
2051: println("for (Node " + ptrName + " = " + name
2052: + ".getFirstChild();");
2053: println(" " + ptrName + " != null;");
2054: println(" " + ptrName + " = " + ptrName
2055: + ".getNextSibling()) {");
2056: pushDepth();
2057: _selectDepth++;
2058: _selectLoopDepth++;
2059:
2060: return ptrName;
2061: } else if (select instanceof FromNextSibling) {
2062: name = printSelectBegin(select.getParent(), isForEach,
2063: loopVar);
2064:
2065: String ptrName = "_xsl_ptr" + _unique++;
2066:
2067: if (loopVar != null && _selectLoopDepth == 0)
2068: println(loopVar + ":");
2069:
2070: println("for (Node " + ptrName + " = " + name
2071: + ".getNextSibling();");
2072: println(" " + ptrName + " != null;");
2073: println(" " + ptrName + " = " + ptrName
2074: + ".getNextSibling()) {");
2075: pushDepth();
2076: _selectDepth++;
2077: _selectLoopDepth++;
2078:
2079: return ptrName;
2080: } else if (select instanceof NodePattern) {
2081: name = printSelectBegin(select.getParent(), isForEach,
2082: loopVar);
2083:
2084: NodePattern pat = (NodePattern) select;
2085:
2086: println("if (" + name + ".getNodeName() == \""
2087: + pat.getNodeName() + "\" &&");
2088: println(" " + name + " instanceof Element) {");
2089: pushDepth();
2090: _selectDepth++;
2091:
2092: return name;
2093: } else if (select instanceof NodeTypePattern) {
2094: name = printSelectBegin(select.getParent(), isForEach,
2095: loopVar);
2096:
2097: NodeTypePattern pat = (NodeTypePattern) select;
2098:
2099: if (pat.getNodeType() >= 0) {
2100: println("if (" + name + ".getNodeType() == "
2101: + pat.getNodeType() + ") {");
2102: pushDepth();
2103: _selectDepth++;
2104: }
2105:
2106: return name;
2107: } else if (select instanceof FilterPattern) {
2108: String posId = "_xsl_pos" + _unique++;
2109:
2110: println("int " + posId + " = 0;");
2111:
2112: name = printSelectBegin(select.getParent(), isForEach,
2113: loopVar);
2114:
2115: println(posId + "++;");
2116:
2117: FilterPattern pat = (FilterPattern) select;
2118: Expr expr = pat.getExpr();
2119:
2120: if (expr instanceof NumericExpr) {
2121: NumericExpr num = (NumericExpr) expr;
2122: if (num.isConstant()) {
2123: println("if (" + posId + " > "
2124: + (int) num.getValue() + ")");
2125: println(" break;");
2126: println("else if (" + posId + " == "
2127: + (int) num.getValue() + ") {");
2128: pushDepth();
2129: _selectDepth++;
2130:
2131: return name;
2132: }
2133: }
2134:
2135: throw new RuntimeException();
2136: }
2137:
2138: throw new RuntimeException(String.valueOf(select));
2139: }
2140:
2141: /**
2142: * Returns true if we can compile in the java select.
2143: */
2144: private boolean allowJavaSelect(AbstractPattern select) {
2145: if (select == null)
2146: return false;
2147:
2148: else if (!select.isStrictlyAscending())
2149: return false;
2150:
2151: else if (select instanceof FromContext)
2152: return ((FromContext) select).getCount() == 0;
2153:
2154: else if (select instanceof FromRoot)
2155: return true;
2156:
2157: else if (select instanceof NodePattern)
2158: return allowJavaSelect(select.getParent());
2159:
2160: else if (select instanceof NodeTypePattern)
2161: return allowJavaSelect(select.getParent());
2162:
2163: else if (select instanceof FromChildren)
2164: return allowJavaSelect(select.getParent());
2165:
2166: else if (select instanceof FromNextSibling)
2167: return allowJavaSelect(select.getParent());
2168:
2169: else if (select instanceof FilterPattern) {
2170: if (!allowJavaSelect(select.getParent()))
2171: return false;
2172:
2173: Expr expr = ((FilterPattern) select).getExpr();
2174:
2175: return ((expr instanceof NumericExpr) && ((NumericExpr) expr)
2176: .isConstant());
2177: }
2178:
2179: else
2180: return false;
2181: }
2182:
2183: private void stringExpr(String exprString, Element element)
2184: throws Exception, XslParseException {
2185: print("_exprs[" + addExpr(exprString) + "].evalString(node, "
2186: + getEnv() + ")");
2187: }
2188:
2189: /**
2190: * Adds an expression constant returning its index.
2191: *
2192: * @param expr the expression to add.
2193: *
2194: * @return the index into the runtime expression array
2195: */
2196: public int addExpr(Expr expr) throws XslParseException {
2197: String exprStr = expr.toString();
2198:
2199: int i = _exprMap.get(exprStr);
2200: if (i >= 0)
2201: return i;
2202:
2203: i = _exprs.size();
2204: _exprMap.put(exprStr, i);
2205: _exprs.add(expr);
2206:
2207: return i;
2208: }
2209:
2210: /**
2211: * Adds an expression constant returning its index.
2212: *
2213: * @param exprString the expression to add.
2214: *
2215: * @return the index into the runtime expression array
2216: */
2217: public int addExpr(String exprString) throws XslParseException {
2218: int i = _exprMap.get(exprString);
2219:
2220: if (i >= 0)
2221: return i;
2222:
2223: Expr expr = parseExpr(exprString);
2224: i = _exprs.size();
2225: _exprs.add(expr);
2226:
2227: _exprMap.put(exprString, i);
2228:
2229: return i;
2230: }
2231:
2232: /**
2233: * Adds a select pattern returning its index.
2234: *
2235: * @param select the select pattern to add.
2236: *
2237: * @return the index into the runtime expression array
2238: */
2239: public int addSelect(AbstractPattern select) throws IOException,
2240: XslParseException {
2241: String selectStr = select.toString();
2242:
2243: int i = _selectMap.get(selectStr);
2244: if (i >= 0)
2245: return i;
2246:
2247: i = _selectPatterns.size();
2248: _selectMap.put(selectStr, i);
2249: _selectPatterns.add(select);
2250:
2251: return i;
2252: }
2253:
2254: /**
2255: * Adds a select pattern, returning its index.
2256: *
2257: * @param selectString the expression to add.
2258: *
2259: * @return the index into the runtime select pattern array
2260: */
2261: public int addSelect(String selectString) throws IOException,
2262: XslParseException {
2263: int i = _selectMap.get(selectString);
2264:
2265: if (i >= 0)
2266: return i;
2267:
2268: AbstractPattern select = parseSelect(selectString);
2269: i = _selectPatterns.size();
2270: _selectPatterns.add(select);
2271:
2272: _selectMap.put(selectString, i);
2273:
2274: return i;
2275: }
2276:
2277: /**
2278: * Adds a match pattern, returning its index.
2279: *
2280: * @param pattern the expression to add.
2281: *
2282: * @return the index into the runtime expression array
2283: */
2284: public int addMatch(AbstractPattern pattern)
2285: throws XslParseException {
2286: int index = _matchPatterns.size();
2287:
2288: _matchPatterns.add(pattern);
2289:
2290: return index;
2291: }
2292:
2293: protected StylesheetImpl completeGenerate(ArrayList<XslNode> inits,
2294: ArrayList globals) throws Exception {
2295: printTemplates();
2296: printMacros();
2297:
2298: printInitVars(inits);
2299: printFragments();
2300:
2301: printInit();
2302:
2303: printStrings();
2304: printExpressions();
2305: printPatterns();
2306:
2307: popDepth();
2308: println("}");
2309: _s.close();
2310: _s = null;
2311:
2312: /*
2313: if (dbg.canWrite()) {
2314: ReadStream is = path.openRead();
2315: dbg.writeStream(is);
2316: is.close();
2317: }
2318: */
2319:
2320: if (_parentLoader instanceof DynamicClassLoader)
2321: ((DynamicClassLoader) _parentLoader).make();
2322:
2323: _compiler.compile(_path.getPath(), _lineMap);
2324:
2325: StylesheetImpl stylesheet;
2326:
2327: stylesheet = (StylesheetImpl) _xslGenerator.loadStylesheet(
2328: _path.getFullPath(), _pkg + "." + _className);
2329: //if (stylesheet != null)
2330: // stylesheet.init(context);
2331:
2332: return stylesheet;
2333: }
2334:
2335: private long getLastModified() {
2336: long lastModified = 0;
2337: for (int i = 0; i < _depends.size(); i++) {
2338: Path path = _depends.get(i);
2339: if (path.getLastModified() > lastModified)
2340: lastModified = path.getLastModified();
2341: }
2342:
2343: return lastModified;
2344: }
2345:
2346: /**
2347: * Generate code executed for all transformations.
2348: * <ul>
2349: * <li>Add the stylesheet namespaces to the generated document.
2350: * <li>Assign the global variables.
2351: * <li>Initialize the cache dependencies.
2352: */
2353: protected void printInitVars(ArrayList<XslNode> inits)
2354: throws Exception {
2355: println("private void _xsl_init_vars(XslWriter out, Node node, Env env)");
2356: println(" throws Exception");
2357: println("{");
2358: pushDepth();
2359:
2360: // Add the stylesheet namespaces to the generated document.
2361: HashMap namespaces = _qDoc.getNamespaces();
2362: if (namespaces != null) {
2363: Iterator prefixes = namespaces.keySet().iterator();
2364: while (prefixes.hasNext()) {
2365: String prefix = (String) prefixes.next();
2366: String url = (String) namespaces.get(prefix);
2367:
2368: if (url.startsWith("http://www.w3.org/XSL/Transform/")
2369: || url
2370: .startsWith("http://www.w3.org/1999/XSL/Transform")
2371: || url
2372: .startsWith("http://www.w3.org/XML/2000/xmlns")
2373: || url
2374: .startsWith("http://www.w3.org/2000/xmlns")
2375: || url.equals(XTPNS))
2376: continue;
2377: else if (_excludedNamespaces.get(url) != null)
2378: continue;
2379: else if (_namespaceAliases.get(url) != null)
2380: continue;
2381:
2382: if (prefix == null)
2383: println("out.addNamespace(\"\", \"" + url + "\");");
2384: else
2385: println("out.addNamespace(\"" + prefix + "\", \""
2386: + url + "\");");
2387: }
2388: }
2389:
2390: // Initialize the global stylesheet variables
2391: println("Object _xsl_tmp;");
2392: for (int i = 0; i < inits.size(); i++) {
2393: XslNode node = inits.get(i);
2394: // NamespaceContext oldNamespace = addNamespace(elt);
2395:
2396: node.generate(getOut());
2397:
2398: /*
2399: if ("variable".equals(getXslLocal(elt)) ||
2400: "assign".equals(getXslLocal(elt))) {
2401: String name = elt.getAttribute("name");
2402: String expr = elt.getAttribute("select");
2403: print("env.setGlobal(\"" + name + "\", ");
2404: if (! expr.equals(""))
2405: printVariableValue(parseExpr(expr));
2406: else
2407: printVariableValue(elt);
2408: println(");");
2409: }
2410: else if ("param".equals(getXslLocal(elt))) {
2411: String name = elt.getAttribute("name");
2412: String expr = elt.getAttribute("select");
2413: print("env.setGlobal(\"" + name + "\", ");
2414: if (! expr.equals(""))
2415: printVariableValue(parseExpr(expr));
2416: else
2417: printVariableValue(elt);
2418: println(");");
2419:
2420: println("_xsl_tmp = out.getParameter(\"" + name + "\");");
2421: println("if (_xsl_tmp != null)");
2422: println(" env.setGlobal(\"" + name + "\", _xsl_tmp);");
2423: }
2424: */
2425:
2426: // oldNamespace = _namespace;
2427: }
2428:
2429: // Initialize the cache dependencies.
2430: println("com.caucho.vfs.Path pwd;");
2431: println("pwd = (com.caucho.vfs.Path) out.getProperty(\"caucho.pwd\");");
2432: for (int i = 0; i < _cacheDepends.size(); i++) {
2433: String depend = (String) _cacheDepends.get(i);
2434:
2435: print("out.addCacheDepend(pwd.lookup(\"");
2436: printString(depend);
2437: println("\"));");
2438: }
2439:
2440: popDepth();
2441: println("}");
2442: }
2443:
2444: protected void printInit() throws Exception {
2445: println("protected void _xsl_init(XslWriter out, Node node, Env env)");
2446: println(" throws Exception");
2447: println("{");
2448: pushDepth();
2449: println("Object _xsl_tmp;");
2450: println("_xsl_init_vars(out, node, env);");
2451:
2452: // Generic init vars
2453: // println("templates = _staticTemplates;");
2454:
2455: for (int i = 0; _globalActions != null
2456: && i < _globalActions.size(); i++) {
2457: QAbstractNode node = (QAbstractNode) _globalActions.get(i);
2458: generateChild(node);
2459: }
2460:
2461: popDepth();
2462: println("}");
2463:
2464: // depends
2465: println("public boolean isModified()");
2466: println("{");
2467: pushDepth();
2468: println("return com.caucho.server.util.CauchoSystem.getVersionId() != "
2469: + CauchoSystem.getVersionId() + "L ||");
2470: println(" super.isModified();");
2471: popDepth();
2472: println("}");
2473:
2474: println("public void init(com.caucho.vfs.Path path)");
2475: println(" throws Exception");
2476: println("{");
2477: pushDepth();
2478: println("super.init(path);");
2479: println("com.caucho.vfs.Path pwd = path.getParent();");
2480:
2481: for (int i = 0; i < _depends.size(); i++) {
2482: Path path = _depends.get(i);
2483:
2484: if (path.canRead() && !path.isDirectory()) {
2485: Depend depend = new Depend(path);
2486:
2487: print("addDepend(new com.caucho.vfs.Depend(pwd.lookup(\"");
2488: printString(path.getRelativePath());
2489: println("\"), " + depend.getDigest() + "L));");
2490: }
2491: }
2492:
2493: println("stylesheets = new StylesheetEnv["
2494: + _stylesheets.size() + "];");
2495: println("StylesheetEnv env;");
2496:
2497: for (int i = 0; i < _stylesheets.size(); i++) {
2498: String ss = _stylesheets.get(i);
2499:
2500: println("env = new StylesheetEnv();");
2501: println("stylesheets[" + i + "] = env;");
2502: print("env.setPath(pwd.lookup(\"");
2503: printString(ss);
2504: println("\"));");
2505: }
2506:
2507: if (!_strip.isEmpty()) {
2508: println("HashMap preserve = new HashMap();");
2509: println("HashMap preservePrefix = new HashMap();");
2510: Iterator iter = _preserve.keySet().iterator();
2511: while (iter.hasNext()) {
2512: String key = (String) iter.next();
2513: if (key.endsWith(":*")) {
2514: String prefix = key.substring(0, key.length() - 2);
2515: println("preservePrefix.put(\"" + prefix
2516: + "\", \"true\");");
2517: } else
2518: println("preserve.put(\"" + key + "\", \"true\");");
2519: }
2520: println("HashMap strip = new HashMap();");
2521: println("HashMap stripPrefix = new HashMap();");
2522: iter = _strip.keySet().iterator();
2523: while (iter.hasNext()) {
2524: String key = (String) iter.next();
2525: if (key.endsWith(":*")) {
2526: String prefix = key.substring(0, key.length() - 2);
2527: println("stripPrefix.put(\"" + prefix
2528: + "\", \"true\");");
2529: } else
2530: println("strip.put(\"" + key + "\", \"true\");");
2531: }
2532: println("setSpaces(preserve, preservePrefix, strip, stripPrefix);");
2533: }
2534:
2535: printOutput();
2536:
2537: if (_errorPage != null) {
2538: print("setProperty(\"caucho.error.page\", \"");
2539: printString(_errorPage);
2540: println("\");");
2541: }
2542:
2543: if (_globalParameters != null && _globalParameters.size() > 0) {
2544: println("ArrayList params = new ArrayList();");
2545: for (int i = 0; i < _globalParameters.size(); i++) {
2546: String param = _globalParameters.get(i);
2547:
2548: println("params.add(\"" + param + "\");");
2549: }
2550: print("setProperty(\"caucho.global.param\", params);");
2551: }
2552:
2553: String disable = null;
2554: /*
2555: if (_outputAttributes != null)
2556: disable = (String) _outputAttributes.get("disable-output-escaping");
2557: if (disable != null && ! disable.equals("no") && ! disable.equals("false"))
2558: println("defaultDisableEscaping = true;");
2559: */
2560:
2561: if (_isRawText)
2562: println("_defaultDisableEscaping = true;");
2563:
2564: printNamespaces();
2565: printFunctions();
2566: printSorts();
2567: printFormats();
2568:
2569: popDepth();
2570: println("}");
2571: }
2572:
2573: /**
2574: * Sets the property for the xsl:output keys.
2575: */
2576: private void printOutput() throws Exception {
2577: Iterator iter = _outputAttributes.keySet().iterator();
2578:
2579: if (_outputAttributes.get("encoding") == null)
2580: println("_output.put(\"encoding\", \"utf-8\");");
2581:
2582: while (iter.hasNext()) {
2583: String key = (String) iter.next();
2584: String value = (String) _outputAttributes.get(key);
2585:
2586: println("_output.put(\"" + key + "\", \"" + value + "\");");
2587: }
2588: }
2589:
2590: private void printSorts() throws Exception {
2591: if (_sorts.size() == 0)
2592: return;
2593:
2594: println();
2595: println("_xsl_sorts = new com.caucho.xsl.Sort[][] { ");
2596: pushDepth();
2597:
2598: for (int i = 0; i < _sorts.size(); i++) {
2599: Sort[] sorts = _sorts.get(i);
2600:
2601: print("new com.caucho.xsl.Sort[] {");
2602:
2603: for (int j = 0; j < sorts.length; j++) {
2604: Sort sort = sorts[j];
2605:
2606: Expr lang = sort.getLang();
2607: Expr caseOrder = sort.getCaseOrder();
2608:
2609: if (lang != null || caseOrder != null) {
2610: print("new com.caucho.xsl.Sort(\""
2611: + sort.getExpr()
2612: + "\", "
2613: + "\""
2614: + sort.getAscending()
2615: + "\", "
2616: + (lang == null ? "null, " : "\"" + lang
2617: + "\", ")
2618: + (caseOrder == null ? "null), " : "\""
2619: + caseOrder + "\"), "));
2620: } else
2621: print("new com.caucho.xsl.Sort(\"" + sort.getExpr()
2622: + "\", " + "\"" + sort.getAscending()
2623: + "\", " + sort.isText() + "), ");
2624: }
2625:
2626: println("},");
2627: }
2628: popDepth();
2629: println("};");
2630: }
2631:
2632: private void printLocale(Locale locale) throws Exception {
2633: String language = locale.getLanguage();
2634: String country = locale.getCountry();
2635: String variant = locale.getVariant();
2636:
2637: if (variant != null && country != null) {
2638: print("new java.util.Locale(\"" + language + "\", " + "\""
2639: + country + "\", \"" + variant + "\")");
2640: } else if (country != null) {
2641: print("new java.util.Locale(\"" + language + "\", " + "\""
2642: + country + "\")");
2643: } else {
2644: print("new java.util.Locale(\"" + language + "\")");
2645: }
2646: }
2647:
2648: private void printFormats() throws Exception {
2649: if (_formats.size() == 0)
2650: return;
2651:
2652: println();
2653: println("_xsl_formats = new XslNumberFormat[] { ");
2654: pushDepth();
2655:
2656: for (int i = 0; i < _formats.size(); i++) {
2657: XslNumberFormat format = (XslNumberFormat) _formats.get(i);
2658:
2659: println("new XslNumberFormat(\"" + format.getFormat()
2660: + "\", \"" + format.getLang() + "\", "
2661: + format.isAlphabetic() + ", \""
2662: + format.getGroupSeparator() + "\", "
2663: + format.getGroupSize() + "),");
2664: }
2665: popDepth();
2666: println("};");
2667: }
2668:
2669: private void printNamespaces() throws Exception {
2670: if (_namespaces.size() == 0)
2671: return;
2672:
2673: println();
2674: println("_namespaces = new NamespaceContext[] { ");
2675: pushDepth();
2676:
2677: for (int i = 0; i < _namespaces.size(); i++) {
2678: NamespaceContext ns = _namespaces.get(i);
2679:
2680: printNamespaceDef(ns);
2681: println(",");
2682: }
2683: popDepth();
2684: println("};");
2685: }
2686:
2687: private void printNamespaceDef(NamespaceContext ns)
2688: throws Exception {
2689: if (ns == null) {
2690: print("null");
2691: return;
2692: }
2693:
2694: print("new NamespaceContext(");
2695: printNamespaceDef(ns.getPrev());
2696: print(", \"" + ns.getPrefix() + "\", \"" + ns.getUrl() + "\")");
2697: }
2698:
2699: private void printFunctions() throws Exception {
2700: println();
2701: println("com.caucho.xsl.fun.KeyFun keyFun = new com.caucho.xsl.fun.KeyFun();");
2702: HashMap keys = _keyFun.getKeys();
2703: Iterator iter = keys.keySet().iterator();
2704: while (iter.hasNext()) {
2705: String name = (String) iter.next();
2706: KeyFun.Key key = (KeyFun.Key) keys.get(name);
2707:
2708: println("keyFun.add(\"" + name + "\", XPath.parseMatch(\""
2709: + key.getMatch()
2710: + "\").getPattern(), XPath.parseExpr(\""
2711: + key.getUse() + "\"));");
2712: }
2713: println("addFunction(\"key\", keyFun);");
2714:
2715: println();
2716: println("com.caucho.xsl.fun.FormatNumberFun formatFun = new com.caucho.xsl.fun.FormatNumberFun();");
2717: println("java.text.DecimalFormatSymbols symbols;");
2718: JavaWriter out = _out;
2719:
2720: HashMap locales = _formatNumberFun.getLocales();
2721: iter = locales.keySet().iterator();
2722: while (iter.hasNext()) {
2723: String name = (String) iter.next();
2724: DecimalFormatSymbols symbols = (DecimalFormatSymbols) locales
2725: .get(name);
2726:
2727: out
2728: .println("symbols = new java.text.DecimalFormatSymbols();");
2729:
2730: out.print("symbols.setDecimalSeparator(\'");
2731: out.printJavaChar(symbols.getDecimalSeparator());
2732: out.println("\');");
2733:
2734: out.print("symbols.setGroupingSeparator(\'");
2735: out.printJavaChar(symbols.getGroupingSeparator());
2736: out.println("\');");
2737:
2738: out.print("symbols.setInfinity(\"");
2739: out.printJavaString(symbols.getInfinity());
2740: out.println("\");");
2741:
2742: out.print("symbols.setMinusSign(\'");
2743: out.printJavaChar(symbols.getMinusSign());
2744: out.println("\');");
2745:
2746: out.print("symbols.setNaN(\"");
2747: out.printJavaString(symbols.getNaN());
2748: out.println("\");");
2749:
2750: out.print("symbols.setPercent(\'");
2751: out.printJavaChar(symbols.getPercent());
2752: out.println("\');");
2753:
2754: out.print("symbols.setPerMill(\'");
2755: out.printJavaChar(symbols.getPerMill());
2756: out.println("\');");
2757:
2758: out.print("symbols.setZeroDigit(\'");
2759: out.printJavaChar(symbols.getZeroDigit());
2760: out.println("\');");
2761:
2762: out.print("symbols.setDigit(\'");
2763: out.printJavaChar(symbols.getDigit());
2764: out.println("\');");
2765:
2766: out.print("symbols.setPatternSeparator(\'");
2767: out.printJavaChar(symbols.getPatternSeparator());
2768: out.println("\');");
2769:
2770: println("formatFun.addLocale(\"" + name + "\", symbols);");
2771: }
2772:
2773: println("addFunction(\"format-number\", formatFun);");
2774: }
2775:
2776: private void printMacros() throws Exception {
2777: /*
2778: for (int i = 0; i < _macros.size(); i++) {
2779: Macro macro = _macros.get(i);
2780:
2781: println("void " + getMacroName(macro.getName()) +
2782: "(XslWriter out, Node inputNode, Env env)");
2783: println(" throws Exception");
2784: println("{");
2785: pushDepth();
2786: println("Object _xsl_tmp;");
2787: println("Node node = inputNode;");
2788: generateChildren(macro.getElement());
2789: popDepth();
2790: println("}");
2791: }
2792: */
2793: }
2794:
2795: private void printFragments() throws Exception {
2796: for (int i = 0; i < _fragments.size(); i++) {
2797: Element elt = (Element) _fragments.get(i);
2798:
2799: println("Object _xsl_fragment" + i
2800: + "(XslWriter out, Node inputNode, Env env )");
2801: println(" throws Exception");
2802: println("{");
2803: pushDepth();
2804: println("Object _xsl_tmp;");
2805: println("Node node = inputNode;");
2806: println("XMLWriter _xsl_frag = out.pushFragment();");
2807: generateChildren(elt);
2808: println("return out.popFragment(_xsl_frag);");
2809: popDepth();
2810: println("}");
2811: }
2812: }
2813:
2814: /**
2815: * Prints the template definitions, i.e. the set of XPath
2816: * match patterns to test a node.
2817: */
2818: private void printTemplates() throws Exception {
2819: for (int j = 0; j < _modes.size(); j++) {
2820: String mode = _modes.get(j);
2821: String modeName = getModeName(mode);
2822:
2823: printApplyNode(mode);
2824:
2825: println();
2826: println("static HashMap _static_templates" + modeName + ";");
2827: println();
2828: println("static {");
2829: pushDepth();
2830: println("_static_templates" + modeName
2831: + " = new HashMap();");
2832: println("Template []values;");
2833:
2834: println("try {");
2835: pushDepth();
2836:
2837: ArrayList defaultTemplateList = (ArrayList) _templates
2838: .get("*");
2839: if (defaultTemplateList == null)
2840: defaultTemplateList = new ArrayList();
2841: println("Template []star = new Template[] {");
2842: pushDepth();
2843: for (int i = 0; i < defaultTemplateList.size(); i++) {
2844: Template template = (Template) defaultTemplateList
2845: .get(i);
2846:
2847: if (template.getMode().equals(mode)) {
2848: printTemplate(template);
2849: println(",");
2850: }
2851: }
2852: popDepth();
2853: println("};");
2854: println();
2855: println("_static_templates" + modeName
2856: + ".put(\"*\", star);");
2857:
2858: int count = _templates.size();
2859:
2860: for (int i = 0; i < count; i += 64)
2861: println("_init_templates" + modeName + "_" + i
2862: + "(star);");
2863:
2864: popDepth();
2865: println("} catch (Exception e) {");
2866: println(" e.printStackTrace();");
2867: println("}");
2868:
2869: popDepth();
2870: println("}");
2871:
2872: for (int i = 0; i < count; i += 64)
2873: printTemplateInitFun(mode, i, 64, defaultTemplateList);
2874: }
2875: }
2876:
2877: /**
2878: * Prints a function to initialize some of the templates.
2879: */
2880: private void printApplyNode(String mode) throws Exception {
2881: String modeName = getModeName(mode);
2882:
2883: print("protected void applyNode" + modeName);
2884: println("(XslWriter out, Node node, Env env, int _xsl_min, int _xsl_max)");
2885: println(" throws Exception");
2886: println("{");
2887: pushDepth();
2888: println("Object _xsl_tmp;");
2889: println();
2890: println("switch (getTemplateId(_static_templates" + modeName
2891: + ", " + "node, env, _xsl_min, _xsl_max)) {");
2892: // XXX: name issue below functions/templateList
2893: for (int i = 0; i < _functions.size(); i++) {
2894: Template template = (Template) _templateList.get(i);
2895:
2896: if (template == null || !template.getMode().equals(mode))
2897: continue;
2898:
2899: println("case " + (i + 1) + ":");
2900: println(" " + _functions.get(i) + "(out, node, env);");
2901: println(" break;");
2902: }
2903: println("default:");
2904: println(" switch (node.getNodeType()) {");
2905: println(" case Node.ELEMENT_NODE:");
2906: println(" case Node.DOCUMENT_NODE:");
2907: println(" case Node.DOCUMENT_FRAGMENT_NODE:");
2908: println(" env.setSelect(node, null);");
2909: println(" for (Node child = node.getFirstChild();");
2910: println(" child != null;");
2911: println(" child = child.getNextSibling()) {");
2912: println(" env.setCurrentNode(child);");
2913: println(" applyNode" + modeName + "(out, child, env, 0, "
2914: + Integer.MAX_VALUE + ");");
2915: println(" }");
2916:
2917: println(" break;");
2918: println(" default:");
2919: println(" applyNodeDefault(out, node, env);");
2920: println(" break;");
2921: println(" }");
2922: println(" break;");
2923: println("}");
2924: popDepth();
2925: println("}");
2926: }
2927:
2928: /**
2929: * Prints a function to initialize some of the templates.
2930: */
2931: private void printTemplateInitFun(String mode, int offset,
2932: int length, ArrayList defaultTemplateList) throws Exception {
2933: String modeName = getModeName(mode);
2934:
2935: println("private static void _init_templates" + modeName + "_"
2936: + offset + "(Template []star)");
2937: println(" throws Exception");
2938: println("{");
2939: pushDepth();
2940:
2941: Iterator<String> iter = _templates.keySet().iterator();
2942: while (iter.hasNext() && length > 0) {
2943: String name = iter.next();
2944:
2945: if (name.equals("*"))
2946: continue;
2947:
2948: ArrayList templateList = (ArrayList) _templates.get(name);
2949:
2950: if (modeTemplateCount(mode, templateList) == 0)
2951: continue;
2952:
2953: if (offset > 0) {
2954: offset--;
2955: continue;
2956: }
2957:
2958: println("_static_templates" + modeName + ".put(\"" + name
2959: + "\", ");
2960: println(" mergeTemplates(star, new Template[] {");
2961: pushDepth();
2962: pushDepth();
2963:
2964: for (int i = 0; i < templateList.size(); i++) {
2965: Template template = (Template) templateList.get(i);
2966:
2967: if (template.getMode().equals(mode)) {
2968: printTemplate(template);
2969: println(",");
2970: }
2971: }
2972:
2973: popDepth();
2974: popDepth();
2975: println("}));");
2976:
2977: length--;
2978: }
2979:
2980: popDepth();
2981: println("}");
2982: }
2983:
2984: /**
2985: * Returns true if the template list contains a template with the given
2986: * mode.
2987: */
2988: private int modeTemplateCount(String mode, ArrayList templateList) {
2989: int count = 0;
2990:
2991: for (int i = 0; i < templateList.size(); i++) {
2992: Template template = (Template) templateList.get(i);
2993:
2994: if (template.getMode().equals(mode))
2995: count++;
2996: }
2997:
2998: return count;
2999: }
3000:
3001: /**
3002: * Prints initialization code for a single template.
3003: */
3004: private void printTemplate(Template template) throws IOException {
3005: print("new Template(");
3006: AbstractPattern pattern = template.getPattern();
3007: print("XPath.parseMatch(\""
3008: + template.getPattern().toPatternString()
3009: + "\").getPattern(), ");
3010: print("\"" + template.getMode() + "\", ");
3011: print(template.getMin() + ", ");
3012: print(template.getMax() + ", ");
3013: print(template.getPriority() + ", ");
3014: print(template.getCount() + ", ");
3015: print("\"" + template.getFunction() + "\", ");
3016: print("" + template.getId() + ")");
3017: }
3018:
3019: /**
3020: * Prints the constant strings.
3021: */
3022: private void printStrings() throws Exception {
3023: for (int j = 0; j < _strings.size(); j++) {
3024: String text = (String) _strings.get(j);
3025:
3026: print("static char[] _xsl_string" + j + " = \"");
3027:
3028: printString(text);
3029:
3030: println("\".toCharArray();");
3031: }
3032: }
3033:
3034: /**
3035: * Prints the precompiled XPath expressions as static variables.
3036: */
3037: private void printExpressions() throws Exception {
3038: if (_exprs.size() == 0)
3039: return;
3040:
3041: println("private static Expr []_exprs;");
3042: println("static {");
3043: pushDepth();
3044: println("try {");
3045: pushDepth();
3046:
3047: println("_exprs = new Expr[] { ");
3048: pushDepth();
3049:
3050: for (int i = 0; i < _exprs.size(); i++) {
3051: Expr expr = _exprs.get(i);
3052:
3053: println("XPath.parseExpr(\"" + expr + "\"),");
3054:
3055: // System.out.println("EXPR: " + expr + " " + expr.getListContext());
3056: /*
3057: if (expr.getListContext() == null) // || currentPos != null)
3058: println("XPath.parseExpr(\"" + expr + "\"),");
3059: else {
3060: print("XPath.parseExpr(\"" + expr + "\", null,");
3061: println("XPath.parseMatch(\"" + expr.getListContext() +"\").getPattern()),");
3062: }
3063: */
3064:
3065: }
3066: popDepth();
3067: println("};");
3068:
3069: popDepth();
3070: println("} catch (Exception e) {");
3071: println(" e.printStackTrace();");
3072: println("}");
3073:
3074: popDepth();
3075: println("}");
3076: }
3077:
3078: /**
3079: * Prints the precompiled XPath select and match patterns as static
3080: * variables.
3081: */
3082: private void printPatterns() throws Exception {
3083: if (_selectPatterns.size() == 0 && _matchPatterns.size() == 0)
3084: return;
3085:
3086: println("private static com.caucho.xpath.pattern.AbstractPattern []_select_patterns;");
3087: println("private static com.caucho.xpath.pattern.AbstractPattern []_match_patterns;");
3088: println("static {");
3089: pushDepth();
3090: println("try {");
3091: pushDepth();
3092:
3093: println("_select_patterns = new com.caucho.xpath.pattern.AbstractPattern[] { ");
3094: pushDepth();
3095:
3096: for (int i = 0; i < _selectPatterns.size(); i++) {
3097: AbstractPattern pattern = _selectPatterns.get(i);
3098:
3099: println("XPath.parseSelect(\"" + pattern
3100: + "\").getPattern(),");
3101: }
3102: popDepth();
3103: println("};");
3104:
3105: println("_match_patterns = new com.caucho.xpath.pattern.AbstractPattern[] { ");
3106: pushDepth();
3107:
3108: for (int i = 0; i < _matchPatterns.size(); i++) {
3109: AbstractPattern pattern = _matchPatterns.get(i);
3110:
3111: println("XPath.parseMatch(\"" + pattern
3112: + "\").getPattern(),");
3113: }
3114: popDepth();
3115: println("};");
3116:
3117: popDepth();
3118: println("} catch (Exception e) {");
3119: println(" e.printStackTrace();");
3120: println("}");
3121:
3122: popDepth();
3123: println("}");
3124: }
3125:
3126: private boolean isSingleStylesheet() {
3127: // return stylesheets.size() < 2;
3128: return false;
3129: }
3130:
3131: /**
3132: * Prints a character to the generated Java.
3133: */
3134: private void print(char ch) throws IOException {
3135: _out.print(ch);
3136: }
3137:
3138: /**
3139: * Prints a string to the generated Java.
3140: */
3141: private void print(String string) throws IOException {
3142: _out.print(string);
3143: }
3144:
3145: /**
3146: * Prints an integer to the generated Java.
3147: */
3148: private void print(int i) throws IOException {
3149: _out.print(i);
3150: }
3151:
3152: /**
3153: * Prints a new line.
3154: */
3155: private void println() throws IOException {
3156: _out.println();
3157: }
3158:
3159: private void println(char ch) throws IOException {
3160: _out.println(ch);
3161: }
3162:
3163: private void println(String s) throws IOException {
3164: _out.println(s);
3165: }
3166:
3167: /**
3168: * Pushes the pretty-printed depth of the generated java.
3169: */
3170: private void pushDepth() throws IOException {
3171: _out.pushDepth();
3172: }
3173:
3174: /**
3175: * Pops the pretty-printed depth of the generated java.
3176: */
3177: private void popDepth() throws IOException {
3178: _out.popDepth();
3179: }
3180:
3181: /**
3182: * Prints the contents of a string, taking care of escapes.
3183: */
3184: protected void printString(String str) throws IOException {
3185: _out.printJavaString(str);
3186: }
3187:
3188: /**
3189: * Returns the name of the applyNode method.
3190: *
3191: * @param mode the template's mode.
3192: */
3193: public String getModeName(String mode) {
3194: if (mode != null && !_modes.contains(mode))
3195: _modes.add(mode);
3196:
3197: if (mode == null || mode.equals(""))
3198: return "";
3199: else
3200: return "_" + toJavaIdentifier(mode);
3201: }
3202:
3203: public void addMode(String mode) {
3204: if (!_modes.contains(mode))
3205: _modes.add(mode);
3206: }
3207:
3208: public int addStylesheet(String filename) {
3209: int pos = _stylesheets.indexOf(filename);
3210:
3211: if (pos < 0) {
3212: pos = _stylesheets.size();
3213: _stylesheets.add(filename);
3214: }
3215:
3216: return pos;
3217: }
3218:
3219: /**
3220: * Converts a string to a Java identifier, encoding unknown characters
3221: * as "_"
3222: */
3223: public String toJavaIdentifier(String name) {
3224: CharBuffer cb = new CharBuffer();
3225:
3226: char ch = name.charAt(0);
3227: if (Character.isJavaIdentifierStart(ch))
3228: cb.append(ch);
3229: else
3230: cb.append("_");
3231:
3232: for (int i = 1; i < name.length(); i++) {
3233: ch = name.charAt(i);
3234:
3235: if (Character.isJavaIdentifierPart(ch))
3236: cb.append(ch);
3237: else {
3238: cb.append("_");
3239: cb.append((char) ((ch & 0xf) + 'a'));
3240: cb.append((char) ((ch / 16 & 0xf) + 'a'));
3241: }
3242: }
3243:
3244: return cb.toString();
3245: }
3246:
3247: /**
3248: * Close call when an error occurs.
3249: */
3250: public void close() throws IOException {
3251: if (_s != null)
3252: _s.close();
3253: }
3254:
3255: static class Macro {
3256: String _name;
3257: Element _elt;
3258:
3259: Macro(String name, Element elt) {
3260: _name = name;
3261: _elt = elt;
3262: }
3263:
3264: public Element getElement() {
3265: return _elt;
3266: }
3267:
3268: public String getName() {
3269: return _name;
3270: }
3271: }
3272:
3273: static {
3274: _tagMap = new HashMap<QName, Class>();
3275:
3276: _tagMap.put(new QName("xsl", "attribute", XSLNS),
3277: XslAttribute.class);
3278: _tagMap.put(new QName("xsl", "attribute-set", XSLNS),
3279: XslAttributeSet.class);
3280: _tagMap.put(new QName("xsl", "apply-imports", XSLNS),
3281: XslApplyImports.class);
3282: _tagMap.put(new QName("xsl", "apply-templates", XSLNS),
3283: XslApplyTemplates.class);
3284: _tagMap.put(new QName("xsl", "call-template", XSLNS),
3285: XslCallTemplate.class);
3286: _tagMap.put(new QName("xsl", "choose", XSLNS), XslChoose.class);
3287: _tagMap.put(new QName("xsl", "comment", XSLNS),
3288: XslComment.class);
3289: _tagMap.put(new QName("xsl", "copy", XSLNS), XslCopy.class);
3290: _tagMap
3291: .put(new QName("xsl", "copy-of", XSLNS),
3292: XslCopyOf.class);
3293: _tagMap.put(new QName("xsl", "decimal-format", XSLNS),
3294: XslDecimalFormat.class);
3295: _tagMap.put(new QName("xsl", "element", XSLNS),
3296: XslElement.class);
3297: _tagMap.put(new QName("xsl", "for-each", XSLNS),
3298: XslForEach.class);
3299: _tagMap.put(new QName("xsl", "if", XSLNS), XslIf.class);
3300: _tagMap.put(new QName("xsl", "import", XSLNS), XslImport.class);
3301: _tagMap.put(new QName("xsl", "include", XSLNS),
3302: XslInclude.class);
3303: _tagMap.put(new QName("xsl", "key", XSLNS), XslKey.class);
3304: _tagMap.put(new QName("xsl", "message", XSLNS),
3305: XslMessage.class);
3306: _tagMap.put(new QName("xsl", "namespace-alias", XSLNS),
3307: XslNamespaceAlias.class);
3308: _tagMap.put(new QName("xsl", "number", XSLNS), XslNumber.class);
3309: _tagMap.put(new QName("xsl", "otherwise", XSLNS),
3310: XslOtherwise.class);
3311: _tagMap.put(new QName("xsl", "output", XSLNS), XslOutput.class);
3312: _tagMap.put(new QName("xsl", "param", XSLNS), XslParam.class);
3313: _tagMap.put(new QName("xsl", "processing-instruction", XSLNS),
3314: XslProcessingInstruction.class);
3315: _tagMap.put(new QName("xsl", "sort", XSLNS), XslSort.class);
3316: _tagMap.put(new QName("xsl", "stylesheet", XSLNS),
3317: XslStylesheet.class);
3318: _tagMap.put(new QName("xsl", "text", XSLNS), XslText.class);
3319: _tagMap.put(new QName("xsl", "transform", XSLNS),
3320: XslTransform.class);
3321: _tagMap.put(new QName("xsl", "value-of", XSLNS),
3322: XslValueOf.class);
3323: _tagMap.put(new QName("xsl", "variable", XSLNS),
3324: XslVariable.class);
3325: _tagMap.put(new QName("xsl", "when", XSLNS), XslWhen.class);
3326: _tagMap.put(new QName("xsl", "with-param", XSLNS),
3327: XslWithParam.class);
3328:
3329: _tagMap.put(new QName("xsl", "template", XSLNS),
3330: XslTemplate.class);
3331: _tagMap.put(new QName("xsl", "strip-space", XSLNS),
3332: XslStripSpace.class);
3333: _tagMap.put(new QName("xsl", "preserve-space", XSLNS),
3334: XslPreserveSpace.class);
3335: _tagMap.put(new QName("xsl", "result-document", XSLNS),
3336: XslResultDocument.class);
3337:
3338: _tagMap.put(new QName("xtp", "expression", XTPNS),
3339: XtpExpression.class);
3340: _tagMap.put(new QName("xtp:expression", null),
3341: XtpExpression.class);
3342: _tagMap.put(new QName("xtp", "eval", XTPNS),
3343: XtpExpression.class);
3344: _tagMap.put(new QName("xtp:eval", null), XtpExpression.class);
3345: _tagMap.put(new QName("xtp", "expr", XTPNS),
3346: XtpExpression.class);
3347: _tagMap.put(new QName("xtp:expr", null), XtpExpression.class);
3348: _tagMap.put(new QName("xtp", "scriptlet", XTPNS),
3349: XtpScriptlet.class);
3350: _tagMap.put(new QName("xtp:scriptlet", null),
3351: XtpScriptlet.class);
3352: _tagMap.put(new QName("xtp", "declaration", XTPNS),
3353: XtpDeclaration.class);
3354: _tagMap.put(new QName("xtp", "decl", XTPNS),
3355: XtpDeclaration.class);
3356: _tagMap.put(new QName("xtp:declaration", null),
3357: XtpDeclaration.class);
3358: _tagMap.put(new QName("xtp:decl", null), XtpDeclaration.class);
3359: _tagMap.put(new QName("xtp:directive.page", null),
3360: XtpDirectivePage.class);
3361: _tagMap.put(new QName("xtp", "directive.page", XTPNS),
3362: XtpDirectivePage.class);
3363: _tagMap.put(new QName("xtp:directive.cache", null),
3364: XtpDirectiveCache.class);
3365: _tagMap.put(new QName("xtp", "directive.cache", XTPNS),
3366: XtpDirectiveCache.class);
3367: _tagMap.put(new QName("xtp:assign", null), XslVariable.class);
3368: _tagMap.put(new QName("xtp", "assign", XTPNS),
3369: XslVariable.class);
3370: }
3371: }
|