org.apache.xalan.xsltc.compiler.util.NodeType Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of serializer Show documentation
Show all versions of serializer Show documentation
Serializer to write out XML, HTML etc. as a stream of characters from an input DOM or from input
SAX events.
/*
* 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: NodeType.java 468649 2006-10-28 07:00:55Z minchau $
*/
package org.apache.xalan.xsltc.compiler.util;
import org.apache.bcel.generic.BranchHandle;
import org.apache.bcel.generic.CHECKCAST;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.GETFIELD;
import org.apache.bcel.generic.GOTO;
import org.apache.bcel.generic.IFEQ;
import org.apache.bcel.generic.ILOAD;
import org.apache.bcel.generic.INVOKEINTERFACE;
import org.apache.bcel.generic.INVOKESPECIAL;
import org.apache.bcel.generic.ISTORE;
import org.apache.bcel.generic.Instruction;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.NEW;
import org.apache.bcel.generic.PUSH;
import org.apache.xalan.xsltc.compiler.Constants;
import org.apache.xalan.xsltc.compiler.FlowList;
import org.apache.xalan.xsltc.compiler.NodeTest;
/**
* @author Jacek Ambroziak
* @author Santiago Pericas-Geertsen
*/
public final class NodeType extends Type {
private final int _type;
protected NodeType() {
this(NodeTest.ANODE);
}
protected NodeType(int type) {
_type = type;
}
public int getType() {
return _type;
}
public String toString() {
return "node-type";
}
public boolean identicalTo(Type other) {
return other instanceof NodeType;
}
public int hashCode() {
return _type;
}
public String toSignature() {
return "I";
}
public org.apache.bcel.generic.Type toJCType() {
return org.apache.bcel.generic.Type.INT;
}
/**
* Translates a node into an object of internal type type
.
* The translation to int is undefined since nodes are always converted
* to reals in arithmetic expressions.
*
* @see org.apache.xalan.xsltc.compiler.util.Type#translateTo
*/
public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
Type type) {
if (type == Type.String) {
translateTo(classGen, methodGen, (StringType) type);
}
else if (type == Type.Boolean) {
translateTo(classGen, methodGen, (BooleanType) type);
}
else if (type == Type.Real) {
translateTo(classGen, methodGen, (RealType) type);
}
else if (type == Type.NodeSet) {
translateTo(classGen, methodGen, (NodeSetType) type);
}
else if (type == Type.Reference) {
translateTo(classGen, methodGen, (ReferenceType) type);
}
else if (type == Type.Object) {
translateTo(classGen, methodGen, (ObjectType) type);
}
else {
ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
toString(), type.toString());
classGen.getParser().reportError(Constants.FATAL, err);
}
}
/**
* Expects a node on the stack and pushes its string value.
*
* @see org.apache.xalan.xsltc.compiler.util.Type#translateTo
*/
public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
StringType type) {
final ConstantPoolGen cpg = classGen.getConstantPool();
final InstructionList il = methodGen.getInstructionList();
switch (_type) {
case NodeTest.ROOT:
case NodeTest.ELEMENT:
il.append(methodGen.loadDOM());
il.append(SWAP); // dom ref must be below node index
int index = cpg.addInterfaceMethodref(DOM_INTF,
GET_ELEMENT_VALUE,
GET_ELEMENT_VALUE_SIG);
il.append(new INVOKEINTERFACE(index, 2));
break;
case NodeTest.ANODE:
case NodeTest.COMMENT:
case NodeTest.ATTRIBUTE:
case NodeTest.PI:
il.append(methodGen.loadDOM());
il.append(SWAP); // dom ref must be below node index
index = cpg.addInterfaceMethodref(DOM_INTF,
GET_NODE_VALUE,
GET_NODE_VALUE_SIG);
il.append(new INVOKEINTERFACE(index, 2));
break;
default:
ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
toString(), type.toString());
classGen.getParser().reportError(Constants.FATAL, err);
break;
}
}
/**
* Translates a node into a synthesized boolean.
* If the expression is "@attr",
* then "true" is pushed iff "attr" is an attribute of the current node.
* If the expression is ".", the result is always "true".
*
* @see org.apache.xalan.xsltc.compiler.util.Type#translateTo
*/
public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
BooleanType type) {
final InstructionList il = methodGen.getInstructionList();
FlowList falsel = translateToDesynthesized(classGen, methodGen, type);
il.append(ICONST_1);
final BranchHandle truec = il.append(new GOTO(null));
falsel.backPatch(il.append(ICONST_0));
truec.setTarget(il.append(NOP));
}
/**
* Expects a node on the stack and pushes a real.
* First the node is converted to string, and from string to real.
*
* @see org.apache.xalan.xsltc.compiler.util.Type#translateTo
*/
public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
RealType type) {
translateTo(classGen, methodGen, Type.String);
Type.String.translateTo(classGen, methodGen, Type.Real);
}
/**
* Expects a node on the stack and pushes a singleton node-set. Singleton
* iterators are already started after construction.
*
* @see org.apache.xalan.xsltc.compiler.util.Type#translateTo
*/
public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
NodeSetType type) {
ConstantPoolGen cpg = classGen.getConstantPool();
InstructionList il = methodGen.getInstructionList();
// Create a new instance of SingletonIterator
il.append(new NEW(cpg.addClass(SINGLETON_ITERATOR)));
il.append(DUP_X1);
il.append(SWAP);
final int init = cpg.addMethodref(SINGLETON_ITERATOR, "",
"(" + NODE_SIG +")V");
il.append(new INVOKESPECIAL(init));
}
/**
* Subsume Node into ObjectType.
*
* @see org.apache.xalan.xsltc.compiler.util.Type#translateTo
*/
public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
ObjectType type) {
methodGen.getInstructionList().append(NOP);
}
/**
* Translates a node into a non-synthesized boolean. It does not push a
* 0 or a 1 but instead returns branchhandle list to be appended to the
* false list.
*
* @see org.apache.xalan.xsltc.compiler.util.Type#translateToDesynthesized
*/
public FlowList translateToDesynthesized(ClassGenerator classGen,
MethodGenerator methodGen,
BooleanType type) {
final InstructionList il = methodGen.getInstructionList();
return new FlowList(il.append(new IFEQ(null)));
}
/**
* Expects a node on the stack and pushes a boxed node. Boxed nodes
* are represented by an instance of org.apache.xalan.xsltc.dom.Node
.
*
* @see org.apache.xalan.xsltc.compiler.util.Type#translateTo
*/
public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
ReferenceType type) {
final ConstantPoolGen cpg = classGen.getConstantPool();
final InstructionList il = methodGen.getInstructionList();
il.append(new NEW(cpg.addClass(RUNTIME_NODE_CLASS)));
il.append(DUP_X1);
il.append(SWAP);
il.append(new PUSH(cpg, _type));
il.append(new INVOKESPECIAL(cpg.addMethodref(RUNTIME_NODE_CLASS,
"", "(II)V")));
}
/**
* Translates a node into the Java type denoted by clazz
.
* Expects a node on the stack and pushes an object of the appropriate
* type after coercion.
*/
public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
Class clazz) {
final ConstantPoolGen cpg = classGen.getConstantPool();
final InstructionList il = methodGen.getInstructionList();
String className = clazz.getName();
if (className.equals("java.lang.String")) {
translateTo(classGen, methodGen, Type.String);
return;
}
il.append(methodGen.loadDOM());
il.append(SWAP); // dom ref must be below node index
if (className.equals("org.w3c.dom.Node") ||
className.equals("java.lang.Object")) {
int index = cpg.addInterfaceMethodref(DOM_INTF,
MAKE_NODE,
MAKE_NODE_SIG);
il.append(new INVOKEINTERFACE(index, 2));
}
else if (className.equals("org.w3c.dom.NodeList")) {
int index = cpg.addInterfaceMethodref(DOM_INTF,
MAKE_NODE_LIST,
MAKE_NODE_LIST_SIG);
il.append(new INVOKEINTERFACE(index, 2));
}
else {
ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
toString(), className);
classGen.getParser().reportError(Constants.FATAL, err);
}
}
/**
* Translates an object of this type to its boxed representation.
*/
public void translateBox(ClassGenerator classGen,
MethodGenerator methodGen) {
translateTo(classGen, methodGen, Type.Reference);
}
/**
* Translates an object of this type to its unboxed representation.
*/
public void translateUnBox(ClassGenerator classGen,
MethodGenerator methodGen) {
final ConstantPoolGen cpg = classGen.getConstantPool();
final InstructionList il = methodGen.getInstructionList();
il.append(new CHECKCAST(cpg.addClass(RUNTIME_NODE_CLASS)));
il.append(new GETFIELD(cpg.addFieldref(RUNTIME_NODE_CLASS,
NODE_FIELD,
NODE_FIELD_SIG)));
}
/**
* Returns the class name of an internal type's external representation.
*/
public String getClassName() {
return(RUNTIME_NODE_CLASS);
}
public Instruction LOAD(int slot) {
return new ILOAD(slot);
}
public Instruction STORE(int slot) {
return new ISTORE(slot);
}
}