Package org.apache.xalan.xsltc.compiler

Source Code of org.apache.xalan.xsltc.compiler.Template

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 468650 2006-10-28 07:03:30Z minchau $
*/

package org.apache.xalan.xsltc.compiler;

import java.util.Vector;

import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.INVOKEVIRTUAL;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.InstructionList;
import org.apache.xalan.xsltc.compiler.util.ClassGenerator;
import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
import org.apache.xalan.xsltc.compiler.util.NamedMethodGenerator;
import org.apache.xalan.xsltc.compiler.util.Type;
import org.apache.xalan.xsltc.compiler.util.TypeCheckError;
import org.apache.xalan.xsltc.compiler.util.Util;
import org.apache.xml.utils.XML11Char;


/**
* @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 (!XML11Char.isXML11ValidQName(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 (!XML11Char.isXML11ValidQName(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);
    }
       
}
TOP

Related Classes of org.apache.xalan.xsltc.compiler.Template

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.