jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Template.java
changeset 12457 c348e06f0e82
parent 6 7f561c08de6b
equal deleted inserted replaced
12324:1d7e6da6adc8 12457:c348e06f0e82
       
     1 /*
       
     2  * reserved comment block
       
     3  * DO NOT REMOVE OR ALTER!
       
     4  */
       
     5 /*
       
     6  * Copyright 2001-2004 The Apache Software Foundation.
       
     7  *
       
     8  * Licensed under the Apache License, Version 2.0 (the "License");
       
     9  * you may not use this file except in compliance with the License.
       
    10  * You may obtain a copy of the License at
       
    11  *
       
    12  *     http://www.apache.org/licenses/LICENSE-2.0
       
    13  *
       
    14  * Unless required by applicable law or agreed to in writing, software
       
    15  * distributed under the License is distributed on an "AS IS" BASIS,
       
    16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    17  * See the License for the specific language governing permissions and
       
    18  * limitations under the License.
       
    19  */
       
    20 /*
       
    21  * $Id: Template.java,v 1.2.4.1 2005/09/12 11:30:11 pvedula Exp $
       
    22  */
       
    23 
       
    24 package com.sun.org.apache.xalan.internal.xsltc.compiler;
       
    25 
       
    26 import java.util.Vector;
       
    27 
       
    28 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
       
    29 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
       
    30 import com.sun.org.apache.bcel.internal.generic.InstructionHandle;
       
    31 import com.sun.org.apache.bcel.internal.generic.InstructionList;
       
    32 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
       
    33 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
       
    34 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
       
    35 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.NamedMethodGenerator;
       
    36 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
       
    37 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
       
    38 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
       
    39 import com.sun.org.apache.xml.internal.utils.XML11Char;
       
    40 
       
    41 
       
    42 /**
       
    43  * @author Jacek Ambroziak
       
    44  * @author Santiago Pericas-Geertsen
       
    45  * @author Morten Jorgensen
       
    46  * @author Erwin Bolwidt <ejb@klomp.org>
       
    47  */
       
    48 public final class Template extends TopLevelElement {
       
    49 
       
    50     private QName   _name;     // The name of the template (if any)
       
    51     private QName   _mode;     // Mode in which this template is instantiated.
       
    52     private Pattern _pattern;  // Matching pattern defined for this template.
       
    53     private double  _priority; // Matching priority of this template.
       
    54     private int     _position; // Position within stylesheet (prio. resolution)
       
    55     private boolean _disabled = false;
       
    56     private boolean _compiled = false;//make sure it is compiled only once
       
    57     private boolean _simplified = false;
       
    58 
       
    59     // True if this is a simple named template. A simple named
       
    60     // template is a template which only has a name but no match pattern.
       
    61     private boolean _isSimpleNamedTemplate = false;
       
    62 
       
    63     // The list of parameters in this template. This is only used
       
    64     // for simple named templates.
       
    65     private Vector  _parameters = new Vector();
       
    66 
       
    67     public boolean hasParams() {
       
    68         return _parameters.size() > 0;
       
    69     }
       
    70 
       
    71     public boolean isSimplified() {
       
    72         return(_simplified);
       
    73     }
       
    74 
       
    75     public void setSimplified() {
       
    76         _simplified = true;
       
    77     }
       
    78 
       
    79     public boolean isSimpleNamedTemplate() {
       
    80         return _isSimpleNamedTemplate;
       
    81     }
       
    82 
       
    83     public void addParameter(Param param) {
       
    84         _parameters.addElement(param);
       
    85     }
       
    86 
       
    87     public Vector getParameters() {
       
    88         return _parameters;
       
    89     }
       
    90 
       
    91     public void disable() {
       
    92         _disabled = true;
       
    93     }
       
    94 
       
    95     public boolean disabled() {
       
    96         return(_disabled);
       
    97     }
       
    98 
       
    99     public double getPriority() {
       
   100         return _priority;
       
   101     }
       
   102 
       
   103     public int getPosition() {
       
   104         return(_position);
       
   105     }
       
   106 
       
   107     public boolean isNamed() {
       
   108         return _name != null;
       
   109     }
       
   110 
       
   111     public Pattern getPattern() {
       
   112         return _pattern;
       
   113     }
       
   114 
       
   115     public QName getName() {
       
   116         return _name;
       
   117     }
       
   118 
       
   119     public void setName(QName qname) {
       
   120         if (_name == null) _name = qname;
       
   121     }
       
   122 
       
   123     public QName getModeName() {
       
   124         return _mode;
       
   125     }
       
   126 
       
   127     /**
       
   128      * Compare this template to another. First checks priority, then position.
       
   129      */
       
   130     public int compareTo(Object template) {
       
   131         Template other = (Template)template;
       
   132         if (_priority > other._priority)
       
   133             return 1;
       
   134         else if (_priority < other._priority)
       
   135             return -1;
       
   136         else if (_position > other._position)
       
   137             return 1;
       
   138         else if (_position < other._position)
       
   139             return -1;
       
   140         else
       
   141             return 0;
       
   142     }
       
   143 
       
   144     public void display(int indent) {
       
   145         Util.println('\n');
       
   146         indent(indent);
       
   147         if (_name != null) {
       
   148             indent(indent);
       
   149             Util.println("name = " + _name);
       
   150         }
       
   151         else if (_pattern != null) {
       
   152             indent(indent);
       
   153             Util.println("match = " + _pattern.toString());
       
   154         }
       
   155         if (_mode != null) {
       
   156             indent(indent);
       
   157             Util.println("mode = " + _mode);
       
   158         }
       
   159         displayContents(indent + IndentIncrement);
       
   160     }
       
   161 
       
   162     private boolean resolveNamedTemplates(Template other, Parser parser) {
       
   163 
       
   164         if (other == null) return true;
       
   165 
       
   166         SymbolTable stable = parser.getSymbolTable();
       
   167 
       
   168         final int us = this.getImportPrecedence();
       
   169         final int them = other.getImportPrecedence();
       
   170 
       
   171         if (us > them) {
       
   172             other.disable();
       
   173             return true;
       
   174         }
       
   175         else if (us < them) {
       
   176             stable.addTemplate(other);
       
   177             this.disable();
       
   178             return true;
       
   179         }
       
   180         else {
       
   181             return false;
       
   182         }
       
   183     }
       
   184 
       
   185     private Stylesheet _stylesheet = null;
       
   186 
       
   187     public Stylesheet getStylesheet() {
       
   188         return _stylesheet;
       
   189     }
       
   190 
       
   191     public void parseContents(Parser parser) {
       
   192 
       
   193         final String name     = getAttribute("name");
       
   194         final String mode     = getAttribute("mode");
       
   195         final String match    = getAttribute("match");
       
   196         final String priority = getAttribute("priority");
       
   197 
       
   198         _stylesheet = super.getStylesheet();
       
   199 
       
   200         if (name.length() > 0) {
       
   201             if (!XML11Char.isXML11ValidQName(name)) {
       
   202                 ErrorMsg err = new ErrorMsg(ErrorMsg.INVALID_QNAME_ERR, name, this);
       
   203                 parser.reportError(Constants.ERROR, err);
       
   204             }
       
   205             _name = parser.getQNameIgnoreDefaultNs(name);
       
   206         }
       
   207 
       
   208         if (mode.length() > 0) {
       
   209             if (!XML11Char.isXML11ValidQName(mode)) {
       
   210                 ErrorMsg err = new ErrorMsg(ErrorMsg.INVALID_QNAME_ERR, mode, this);
       
   211                 parser.reportError(Constants.ERROR, err);
       
   212             }
       
   213             _mode = parser.getQNameIgnoreDefaultNs(mode);
       
   214         }
       
   215 
       
   216         if (match.length() > 0) {
       
   217             _pattern = parser.parsePattern(this, "match", null);
       
   218         }
       
   219 
       
   220         if (priority.length() > 0) {
       
   221             _priority = Double.parseDouble(priority);
       
   222         }
       
   223         else {
       
   224             if (_pattern != null)
       
   225                 _priority = _pattern.getPriority();
       
   226             else
       
   227                 _priority = Double.NaN;
       
   228         }
       
   229 
       
   230         _position = parser.getTemplateIndex();
       
   231 
       
   232         // Add the (named) template to the symbol table
       
   233         if (_name != null) {
       
   234             Template other = parser.getSymbolTable().addTemplate(this);
       
   235             if (!resolveNamedTemplates(other, parser)) {
       
   236                 ErrorMsg err =
       
   237                     new ErrorMsg(ErrorMsg.TEMPLATE_REDEF_ERR, _name, this);
       
   238                 parser.reportError(Constants.ERROR, err);
       
   239             }
       
   240             // Is this a simple named template?
       
   241             if (_pattern == null && _mode == null) {
       
   242                 _isSimpleNamedTemplate = true;
       
   243             }
       
   244         }
       
   245 
       
   246         if (_parent instanceof Stylesheet) {
       
   247             ((Stylesheet)_parent).addTemplate(this);
       
   248         }
       
   249 
       
   250         parser.setTemplate(this);       // set current template
       
   251         parseChildren(parser);
       
   252         parser.setTemplate(null);       // clear template
       
   253     }
       
   254 
       
   255     /**
       
   256      * When the parser realises that it is dealign with a simplified stylesheet
       
   257      * it will create an empty Stylesheet object with the root element of the
       
   258      * stylesheet (a LiteralElement object) as its only child. The Stylesheet
       
   259      * object will then create this Template object and invoke this method to
       
   260      * force some specific behaviour. What we need to do is:
       
   261      *  o) create a pattern matching on the root node
       
   262      *  o) add the LRE root node (the only child of the Stylesheet) as our
       
   263      *     only child node
       
   264      *  o) set the empty Stylesheet as our parent
       
   265      *  o) set this template as the Stylesheet's only child
       
   266      */
       
   267     public void parseSimplified(Stylesheet stylesheet, Parser parser) {
       
   268 
       
   269         _stylesheet = stylesheet;
       
   270         setParent(stylesheet);
       
   271 
       
   272         _name = null;
       
   273         _mode = null;
       
   274         _priority = Double.NaN;
       
   275         _pattern = parser.parsePattern(this, "/");
       
   276 
       
   277         final Vector contents = _stylesheet.getContents();
       
   278         final SyntaxTreeNode root = (SyntaxTreeNode)contents.elementAt(0);
       
   279 
       
   280         if (root instanceof LiteralElement) {
       
   281             addElement(root);
       
   282             root.setParent(this);
       
   283             contents.set(0, this);
       
   284             parser.setTemplate(this);
       
   285             root.parseContents(parser);
       
   286             parser.setTemplate(null);
       
   287         }
       
   288     }
       
   289 
       
   290     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
       
   291         if (_pattern != null) {
       
   292             _pattern.typeCheck(stable);
       
   293         }
       
   294 
       
   295         return typeCheckContents(stable);
       
   296     }
       
   297 
       
   298     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
       
   299         final ConstantPoolGen cpg = classGen.getConstantPool();
       
   300         final InstructionList il = methodGen.getInstructionList();
       
   301 
       
   302         if (_disabled) return;
       
   303         // bug fix #4433133, add a call to named template from applyTemplates
       
   304         String className = classGen.getClassName();
       
   305 
       
   306         if (_compiled && isNamed()){
       
   307             String methodName = Util.escape(_name.toString());
       
   308             il.append(classGen.loadTranslet());
       
   309             il.append(methodGen.loadDOM());
       
   310             il.append(methodGen.loadIterator());
       
   311             il.append(methodGen.loadHandler());
       
   312             il.append(methodGen.loadCurrentNode());
       
   313             il.append(new INVOKEVIRTUAL(cpg.addMethodref(className,
       
   314                                                          methodName,
       
   315                                                          "("
       
   316                                                          + DOM_INTF_SIG
       
   317                                                          + NODE_ITERATOR_SIG
       
   318                                                          + TRANSLET_OUTPUT_SIG
       
   319                                                          + "I)V")));
       
   320             return;
       
   321         }
       
   322 
       
   323         if (_compiled) return;
       
   324         _compiled = true;
       
   325 
       
   326         // %OPT% Special handling for simple named templates.
       
   327         if (_isSimpleNamedTemplate && methodGen instanceof NamedMethodGenerator) {
       
   328             int numParams = _parameters.size();
       
   329             NamedMethodGenerator namedMethodGen = (NamedMethodGenerator)methodGen;
       
   330 
       
   331             // Update load/store instructions to access Params from the stack
       
   332             for (int i = 0; i < numParams; i++) {
       
   333                 Param param = (Param)_parameters.elementAt(i);
       
   334                 param.setLoadInstruction(namedMethodGen.loadParameter(i));
       
   335                 param.setStoreInstruction(namedMethodGen.storeParameter(i));
       
   336             }
       
   337         }
       
   338 
       
   339         translateContents(classGen, methodGen);
       
   340         il.setPositions(true);
       
   341     }
       
   342 
       
   343 }