org.apache.xalan.xsltc.compiler.WithParam Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xalan Show documentation
Show all versions of xalan Show documentation
Xalan-Java is an XSLT processor for transforming XML documents into HTML,
text, or other XML document types. It implements XSL Transformations (XSLT)
Version 1.0 and XML Path Language (XPath) Version 1.0 and can be used from
the command line, in an applet or a servlet, or as a module in other program.
/*
* 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: WithParam.java 468650 2006-10-28 07:03:30Z minchau $
*/
package org.apache.xalan.xsltc.compiler;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.INVOKEVIRTUAL;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.PUSH;
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.ReferenceType;
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 John Howard
*/
final class WithParam extends Instruction {
/**
* Parameter's name.
*/
private QName _name;
/**
* The escaped qname of the with-param.
*/
protected String _escapedName;
/**
* Parameter's default value.
*/
private Expression _select;
/**
* %OPT% This is set to true when the WithParam is used in a CallTemplate
* for a simple named template. If this is true, the parameters are
* passed to the named template through method arguments rather than
* using the expensive Translet.addParameter() call.
*/
private boolean _doParameterOptimization = false;
/**
* Displays the contents of this element
*/
public void display(int indent) {
indent(indent);
Util.println("with-param " + _name);
if (_select != null) {
indent(indent + IndentIncrement);
Util.println("select " + _select.toString());
}
displayContents(indent + IndentIncrement);
}
/**
* Returns the escaped qname of the parameter
*/
public String getEscapedName() {
return _escapedName;
}
/**
* Return the name of this WithParam.
*/
public QName getName() {
return _name;
}
/**
* Set the name of the variable or paremeter. Escape all special chars.
*/
public void setName(QName name) {
_name = name;
_escapedName = Util.escape(name.getStringRep());
}
/**
* Set the do parameter optimization flag
*/
public void setDoParameterOptimization(boolean flag) {
_doParameterOptimization = flag;
}
/**
* The contents of a elements are either in the element's
* 'select' attribute (this has precedence) or in the element body.
*/
public void parseContents(Parser parser) {
final String name = getAttribute("name");
if (name.length() > 0) {
if (!XML11Char.isXML11ValidQName(name)) {
ErrorMsg err = new ErrorMsg(ErrorMsg.INVALID_QNAME_ERR, name,
this);
parser.reportError(Constants.ERROR, err);
}
setName(parser.getQNameIgnoreDefaultNs(name));
}
else {
reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "name");
}
final String select = getAttribute("select");
if (select.length() > 0) {
_select = parser.parseExpression(this, "select", null);
}
parseChildren(parser);
}
/**
* Type-check either the select attribute or the element body, depending
* on which is in use.
*/
public Type typeCheck(SymbolTable stable) throws TypeCheckError {
if (_select != null) {
final Type tselect = _select.typeCheck(stable);
if (tselect instanceof ReferenceType == false) {
_select = new CastExpr(_select, Type.Reference);
}
}
else {
typeCheckContents(stable);
}
return Type.Void;
}
/**
* Compile the value of the parameter, which is either in an expression in
* a 'select' attribute, or in the with-param element's body
*/
public void translateValue(ClassGenerator classGen,
MethodGenerator methodGen) {
// Compile expression is 'select' attribute if present
if (_select != null) {
_select.translate(classGen, methodGen);
_select.startIterator(classGen, methodGen);
}
// If not, compile result tree from parameter body if present.
else if (hasContents()) {
compileResultTree(classGen, methodGen);
}
// If neither are present then store empty string in parameter slot
else {
final ConstantPoolGen cpg = classGen.getConstantPool();
final InstructionList il = methodGen.getInstructionList();
il.append(new PUSH(cpg, Constants.EMPTYSTRING));
}
}
/**
* This code generates a sequence of bytecodes that call the
* addParameter() method in AbstractTranslet. The method call will add
* (or update) the parameter frame with the new parameter value.
*/
public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
final ConstantPoolGen cpg = classGen.getConstantPool();
final InstructionList il = methodGen.getInstructionList();
// Translate the value and put it on the stack
if (_doParameterOptimization) {
translateValue(classGen, methodGen);
return;
}
// Make name acceptable for use as field name in class
String name = Util.escape(getEscapedName());
// Load reference to the translet (method is in AbstractTranslet)
il.append(classGen.loadTranslet());
// Load the name of the parameter
il.append(new PUSH(cpg, name)); // TODO: namespace ?
// Generete the value of the parameter (use value in 'select' by def.)
translateValue(classGen, methodGen);
// Mark this parameter value is not being the default value
il.append(new PUSH(cpg, false));
// Pass the parameter to the template
il.append(new INVOKEVIRTUAL(cpg.addMethodref(TRANSLET_CLASS,
ADD_PARAMETER,
ADD_PARAMETER_SIG)));
il.append(POP); // cleanup stack
}
}