- /*
- * Copyright 2001-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /*
- * $Id: Template.java,v 1.25 2004/02/24 03:55:48 zongaro Exp $
- */
-
- package com.sun.org.apache.xalan.internal.xsltc.compiler;
-
- import java.util.Vector;
-
- import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
- import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
- import com.sun.org.apache.bcel.internal.generic.InstructionHandle;
- import com.sun.org.apache.bcel.internal.generic.InstructionList;
- import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
- import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
- import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
- import com.sun.org.apache.xalan.internal.xsltc.compiler.util.NamedMethodGenerator;
- import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
- import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
- import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
- import com.sun.org.apache.xml.internal.utils.XMLChar;
-
-
- /**
- * @author Jacek Ambroziak
- * @author Santiago Pericas-Geertsen
- * @author Morten Jorgensen
- * @author Erwin Bolwidt <ejb@klomp.org>
- */
- public final class Template extends TopLevelElement {
-
- private QName _name; // The name of the template (if any)
- private QName _mode; // Mode in which this template is instantiated.
- private Pattern _pattern; // Matching pattern defined for this template.
- private double _priority; // Matching priority of this template.
- private int _position; // Position within stylesheet (prio. resolution)
- private boolean _disabled = false;
- private boolean _compiled = false;//make sure it is compiled only once
- private boolean _simplified = false;
-
- // True if this is a simple named template. A simple named
- // template is a template which only has a name but no match pattern.
- private boolean _isSimpleNamedTemplate = false;
-
- // The list of parameters in this template. This is only used
- // for simple named templates.
- private Vector _parameters = new Vector();
-
- public boolean hasParams() {
- return _parameters.size() > 0;
- }
-
- public boolean isSimplified() {
- return(_simplified);
- }
-
- public void setSimplified() {
- _simplified = true;
- }
-
- public boolean isSimpleNamedTemplate() {
- return _isSimpleNamedTemplate;
- }
-
- public void addParameter(Param param) {
- _parameters.addElement(param);
- }
-
- public Vector getParameters() {
- return _parameters;
- }
-
- public void disable() {
- _disabled = true;
- }
-
- public boolean disabled() {
- return(_disabled);
- }
-
- public double getPriority() {
- return _priority;
- }
-
- public int getPosition() {
- return(_position);
- }
-
- public boolean isNamed() {
- return _name != null;
- }
-
- public Pattern getPattern() {
- return _pattern;
- }
-
- public QName getName() {
- return _name;
- }
-
- public void setName(QName qname) {
- if (_name == null) _name = qname;
- }
-
- public QName getModeName() {
- return _mode;
- }
-
- /**
- * Compare this template to another. First checks priority, then position.
- */
- public int compareTo(Object template) {
- Template other = (Template)template;
- if (_priority > other._priority)
- return 1;
- else if (_priority < other._priority)
- return -1;
- else if (_position > other._position)
- return 1;
- else if (_position < other._position)
- return -1;
- else
- return 0;
- }
-
- public void display(int indent) {
- Util.println('\n');
- indent(indent);
- if (_name != null) {
- indent(indent);
- Util.println("name = " + _name);
- }
- else if (_pattern != null) {
- indent(indent);
- Util.println("match = " + _pattern.toString());
- }
- if (_mode != null) {
- indent(indent);
- Util.println("mode = " + _mode);
- }
- displayContents(indent + IndentIncrement);
- }
-
- private boolean resolveNamedTemplates(Template other, Parser parser) {
-
- if (other == null) return true;
-
- SymbolTable stable = parser.getSymbolTable();
-
- final int us = this.getImportPrecedence();
- final int them = other.getImportPrecedence();
-
- if (us > them) {
- other.disable();
- return true;
- }
- else if (us < them) {
- stable.addTemplate(other);
- this.disable();
- return true;
- }
- else {
- return false;
- }
- }
-
- private Stylesheet _stylesheet = null;
-
- public Stylesheet getStylesheet() {
- return _stylesheet;
- }
-
- public void parseContents(Parser parser) {
-
- final String name = getAttribute("name");
- final String mode = getAttribute("mode");
- final String match = getAttribute("match");
- final String priority = getAttribute("priority");
-
- _stylesheet = super.getStylesheet();
-
- if (name.length() > 0) {
- if (!XMLChar.isValidQName(name)) {
- ErrorMsg err = new ErrorMsg(ErrorMsg.INVALID_QNAME_ERR, name, this);
- parser.reportError(Constants.ERROR, err);
- }
- _name = parser.getQNameIgnoreDefaultNs(name);
- }
-
- if (mode.length() > 0) {
- if (!XMLChar.isValidQName(mode)) {
- ErrorMsg err = new ErrorMsg(ErrorMsg.INVALID_QNAME_ERR, mode, this);
- parser.reportError(Constants.ERROR, err);
- }
- _mode = parser.getQNameIgnoreDefaultNs(mode);
- }
-
- if (match.length() > 0) {
- _pattern = parser.parsePattern(this, "match", null);
- }
-
- if (priority.length() > 0) {
- _priority = Double.parseDouble(priority);
- }
- else {
- if (_pattern != null)
- _priority = _pattern.getPriority();
- else
- _priority = Double.NaN;
- }
-
- _position = parser.getTemplateIndex();
-
- // Add the (named) template to the symbol table
- if (_name != null) {
- Template other = parser.getSymbolTable().addTemplate(this);
- if (!resolveNamedTemplates(other, parser)) {
- ErrorMsg err =
- new ErrorMsg(ErrorMsg.TEMPLATE_REDEF_ERR, _name, this);
- parser.reportError(Constants.ERROR, err);
- }
- // Is this a simple named template?
- if (_pattern == null && _mode == null) {
- _isSimpleNamedTemplate = true;
- }
- }
-
- if (_parent instanceof Stylesheet) {
- ((Stylesheet)_parent).addTemplate(this);
- }
-
- parser.setTemplate(this); // set current template
- parseChildren(parser);
- parser.setTemplate(null); // clear template
- }
-
- /**
- * When the parser realises that it is dealign with a simplified stylesheet
- * it will create an empty Stylesheet object with the root element of the
- * stylesheet (a LiteralElement object) as its only child. The Stylesheet
- * object will then create this Template object and invoke this method to
- * force some specific behaviour. What we need to do is:
- * o) create a pattern matching on the root node
- * o) add the LRE root node (the only child of the Stylesheet) as our
- * only child node
- * o) set the empty Stylesheet as our parent
- * o) set this template as the Stylesheet's only child
- */
- public void parseSimplified(Stylesheet stylesheet, Parser parser) {
-
- _stylesheet = stylesheet;
- setParent(stylesheet);
-
- _name = null;
- _mode = null;
- _priority = Double.NaN;
- _pattern = parser.parsePattern(this, "/");
-
- final Vector contents = _stylesheet.getContents();
- final SyntaxTreeNode root = (SyntaxTreeNode)contents.elementAt(0);
-
- if (root instanceof LiteralElement) {
- addElement(root);
- root.setParent(this);
- contents.set(0, this);
- parser.setTemplate(this);
- root.parseContents(parser);
- parser.setTemplate(null);
- }
- }
-
- public Type typeCheck(SymbolTable stable) throws TypeCheckError {
- if (_pattern != null) {
- _pattern.typeCheck(stable);
- }
-
- return typeCheckContents(stable);
- }
-
- public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
- final ConstantPoolGen cpg = classGen.getConstantPool();
- final InstructionList il = methodGen.getInstructionList();
-
- if (_disabled) return;
- // bug fix #4433133, add a call to named template from applyTemplates
- String className = classGen.getClassName();
-
- if (_compiled && isNamed()){
- String methodName = Util.escape(_name.toString());
- il.append(classGen.loadTranslet());
- il.append(methodGen.loadDOM());
- il.append(methodGen.loadIterator());
- il.append(methodGen.loadHandler());
- il.append(methodGen.loadCurrentNode());
- il.append(new INVOKEVIRTUAL(cpg.addMethodref(className,
- methodName,
- "("
- + DOM_INTF_SIG
- + NODE_ITERATOR_SIG
- + TRANSLET_OUTPUT_SIG
- + "I)V")));
- return;
- }
-
- if (_compiled) return;
- _compiled = true;
-
- // %OPT% Special handling for simple named templates.
- if (_isSimpleNamedTemplate && methodGen instanceof NamedMethodGenerator) {
- int numParams = _parameters.size();
- NamedMethodGenerator namedMethodGen = (NamedMethodGenerator)methodGen;
-
- // Update load/store instructions to access Params from the stack
- for (int i = 0; i < numParams; i++) {
- Param param = (Param)_parameters.elementAt(i);
- param.setLoadInstruction(namedMethodGen.loadParameter(i));
- param.setStoreInstruction(namedMethodGen.storeParameter(i));
- }
- }
-
- translateContents(classGen, methodGen);
- il.setPositions(true);
- }
-
- }