/*
 * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
 */
/*
 * 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.
 */

package com.sun.org.apache.xalan.internal.xsltc.compiler.util;

import com.sun.org.apache.bcel.internal.generic.ALOAD;
import com.sun.org.apache.bcel.internal.generic.ASTORE;
import com.sun.org.apache.bcel.internal.generic.CHECKCAST;
import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
import com.sun.org.apache.bcel.internal.generic.GETFIELD;
import com.sun.org.apache.bcel.internal.generic.IFEQ;
import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL;
import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
import com.sun.org.apache.bcel.internal.generic.Instruction;
import com.sun.org.apache.bcel.internal.generic.InstructionList;
import com.sun.org.apache.bcel.internal.generic.LocalVariableGen;
import com.sun.org.apache.bcel.internal.generic.NEW;
import com.sun.org.apache.bcel.internal.generic.PUSH;
import com.sun.org.apache.xalan.internal.xsltc.compiler.Constants;
import com.sun.org.apache.xalan.internal.xsltc.compiler.FlowList;

Author:Jacek Ambroziak, Santiago Pericas-Geertsen, Morten Jorgensen
@LastModified: Oct 2017
/** * @author Jacek Ambroziak * @author Santiago Pericas-Geertsen * @author Morten Jorgensen * @LastModified: Oct 2017 */
public final class ResultTreeType extends Type { private final String _methodName; protected ResultTreeType() { _methodName = null; } public ResultTreeType(String methodName) { _methodName = methodName; } public String toString() { return "result-tree"; } public boolean identicalTo(Type other) { return (other instanceof ResultTreeType); } public String toSignature() { return DOM_INTF_SIG; } public com.sun.org.apache.bcel.internal.generic.Type toJCType() { return Util.getJCRefType(toSignature()); } public String getMethodName() { return _methodName; } public boolean implementedAsMethod() { return _methodName != null; }
Translates a result tree to object of internal type type. The translation to int is undefined since result trees are always converted to reals in arithmetic expressions.
Params:
  • classGen – A BCEL class generator
  • methodGen – A BCEL method generator
  • type – An instance of the type to translate the result tree to
See Also:
/** * Translates a result tree to object of internal type <code>type</code>. * The translation to int is undefined since result trees * are always converted to reals in arithmetic expressions. * * @param classGen A BCEL class generator * @param methodGen A BCEL method generator * @param type An instance of the type to translate the result tree to * @see com.sun.org.apache.xalan.internal.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 an result tree on the stack and pushes a boolean. Translates a result tree to a boolean by first converting it to string.
Params:
  • classGen – A BCEL class generator
  • methodGen – A BCEL method generator
  • type – An instance of BooleanType (any)
See Also:
/** * Expects an result tree on the stack and pushes a boolean. * Translates a result tree to a boolean by first converting it to string. * * @param classGen A BCEL class generator * @param methodGen A BCEL method generator * @param type An instance of BooleanType (any) * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo */
public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, BooleanType type) { // A result tree is always 'true' when converted to a boolean value, // since the tree always has at least one node (the root). final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); il.append(POP); // don't need the DOM reference il.append(ICONST_1); // push 'true' on the stack }
Expects an result tree on the stack and pushes a string.
Params:
  • classGen – A BCEL class generator
  • methodGen – A BCEL method generator
  • type – An instance of StringType (any)
See Also:
/** * Expects an result tree on the stack and pushes a string. * * @param classGen A BCEL class generator * @param methodGen A BCEL method generator * @param type An instance of StringType (any) * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo */
public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, StringType type) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); if (_methodName == null) { int index = cpg.addInterfaceMethodref(DOM_INTF, "getStringValue", "()"+STRING_SIG); il.append(new INVOKEINTERFACE(index, 1)); } else { final String className = classGen.getClassName(); final int current = methodGen.getLocalIndex("current"); // Push required parameters il.append(classGen.loadTranslet()); if (classGen.isExternal()) { il.append(new CHECKCAST(cpg.addClass(className))); } il.append(DUP); il.append(new GETFIELD(cpg.addFieldref(className, "_dom", DOM_INTF_SIG))); // Create a new instance of a StringValueHandler int index = cpg.addMethodref(STRING_VALUE_HANDLER, "<init>", "()V"); il.append(new NEW(cpg.addClass(STRING_VALUE_HANDLER))); il.append(DUP); il.append(DUP); il.append(new INVOKESPECIAL(index)); // Store new Handler into a local variable final LocalVariableGen handler = methodGen.addLocalVariable("rt_to_string_handler", Util.getJCRefType(STRING_VALUE_HANDLER_SIG), null, null); handler.setStart(il.append(new ASTORE(handler.getIndex()))); // Call the method that implements this result tree index = cpg.addMethodref(className, _methodName, "("+DOM_INTF_SIG+TRANSLET_OUTPUT_SIG+")V"); il.append(new INVOKEVIRTUAL(index)); // Restore new handler and call getValue() handler.setEnd(il.append(new ALOAD(handler.getIndex()))); index = cpg.addMethodref(STRING_VALUE_HANDLER, "getValue", "()" + STRING_SIG); il.append(new INVOKEVIRTUAL(index)); } }
Expects an result tree on the stack and pushes a real. Translates a result tree into a real by first converting it to string.
Params:
  • classGen – A BCEL class generator
  • methodGen – A BCEL method generator
  • type – An instance of RealType (any)
See Also:
/** * Expects an result tree on the stack and pushes a real. * Translates a result tree into a real by first converting it to string. * * @param classGen A BCEL class generator * @param methodGen A BCEL method generator * @param type An instance of RealType (any) * @see com.sun.org.apache.xalan.internal.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 result tree on the stack and pushes a boxed result tree. Result trees are already boxed so the translation is just a NOP.
Params:
  • classGen – A BCEL class generator
  • methodGen – A BCEL method generator
  • type – An instance of ReferenceType (any)
See Also:
/** * Expects a result tree on the stack and pushes a boxed result tree. * Result trees are already boxed so the translation is just a NOP. * * @param classGen A BCEL class generator * @param methodGen A BCEL method generator * @param type An instance of ReferenceType (any) * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo */
public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, ReferenceType type) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); if (_methodName == null) { il.append(NOP); } else { LocalVariableGen domBuilder, newDom; final String className = classGen.getClassName(); final int current = methodGen.getLocalIndex("current"); // Push required parameters il.append(classGen.loadTranslet()); if (classGen.isExternal()) { il.append(new CHECKCAST(cpg.addClass(className))); } il.append(methodGen.loadDOM()); // Create new instance of DOM class (with RTF_INITIAL_SIZE nodes) il.append(methodGen.loadDOM()); int index = cpg.addInterfaceMethodref(DOM_INTF, "getResultTreeFrag", "(IZ)" + DOM_INTF_SIG); il.append(new PUSH(cpg, RTF_INITIAL_SIZE)); il.append(new PUSH(cpg, false)); il.append(new INVOKEINTERFACE(index,3)); il.append(DUP); // Store new DOM into a local variable newDom = methodGen.addLocalVariable("rt_to_reference_dom", Util.getJCRefType(DOM_INTF_SIG), null, null); il.append(new CHECKCAST(cpg.addClass(DOM_INTF_SIG))); newDom.setStart(il.append(new ASTORE(newDom.getIndex()))); // Overwrite old handler with DOM handler index = cpg.addInterfaceMethodref(DOM_INTF, "getOutputDomBuilder", "()" + TRANSLET_OUTPUT_SIG); il.append(new INVOKEINTERFACE(index,1)); //index = cpg.addMethodref(DOM_IMPL, // "getOutputDomBuilder", // "()" + TRANSLET_OUTPUT_SIG); //il.append(new INVOKEVIRTUAL(index)); il.append(DUP); il.append(DUP); // Store DOM handler in a local in order to call endDocument() domBuilder = methodGen.addLocalVariable("rt_to_reference_handler", Util.getJCRefType(TRANSLET_OUTPUT_SIG), null, null); domBuilder.setStart(il.append(new ASTORE(domBuilder.getIndex()))); // Call startDocument on the new handler index = cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE, "startDocument", "()V"); il.append(new INVOKEINTERFACE(index, 1)); // Call the method that implements this result tree index = cpg.addMethodref(className, _methodName, "(" + DOM_INTF_SIG + TRANSLET_OUTPUT_SIG +")V"); il.append(new INVOKEVIRTUAL(index)); // Call endDocument on the DOM handler domBuilder.setEnd(il.append(new ALOAD(domBuilder.getIndex()))); index = cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE, "endDocument", "()V"); il.append(new INVOKEINTERFACE(index, 1)); // Push the new DOM on the stack newDom.setEnd(il.append(new ALOAD(newDom.getIndex()))); } }
Expects a result tree on the stack and pushes a node-set (iterator). Note that the produced iterator is an iterator for the DOM that contains the result tree, and not the DOM that is currently in use. This conversion here will therefore not directly work with elements such as and without the DOM parameter/variable being updates as well.
Params:
  • classGen – A BCEL class generator
  • methodGen – A BCEL method generator
  • type – An instance of NodeSetType (any)
See Also:
/** * Expects a result tree on the stack and pushes a node-set (iterator). * Note that the produced iterator is an iterator for the DOM that * contains the result tree, and not the DOM that is currently in use. * This conversion here will therefore not directly work with elements * such as <xsl:apply-templates> and <xsl:for-each> without the DOM * parameter/variable being updates as well. * * @param classGen A BCEL class generator * @param methodGen A BCEL method generator * @param type An instance of NodeSetType (any) * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo */
public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, NodeSetType type) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); // Put an extra copy of the result tree (DOM) on the stack il.append(DUP); // DOM adapters containing a result tree are not initialised with // translet-type to DOM-type mapping. This must be done now for // XPath expressions and patterns to work for the iterator we create. il.append(classGen.loadTranslet()); // get names array il.append(new GETFIELD(cpg.addFieldref(TRANSLET_CLASS, NAMES_INDEX, NAMES_INDEX_SIG))); il.append(classGen.loadTranslet()); // get uris array il.append(new GETFIELD(cpg.addFieldref(TRANSLET_CLASS, URIS_INDEX, URIS_INDEX_SIG))); il.append(classGen.loadTranslet()); // get types array il.append(new GETFIELD(cpg.addFieldref(TRANSLET_CLASS, TYPES_INDEX, TYPES_INDEX_SIG))); il.append(classGen.loadTranslet()); // get namespaces array il.append(new GETFIELD(cpg.addFieldref(TRANSLET_CLASS, NAMESPACE_INDEX, NAMESPACE_INDEX_SIG))); // Pass the type mappings to the DOM adapter final int mapping = cpg.addInterfaceMethodref(DOM_INTF, "setupMapping", "(["+STRING_SIG+ "["+STRING_SIG+ "[I" + "["+STRING_SIG+")V"); il.append(new INVOKEINTERFACE(mapping, 5)); il.append(DUP); // Create an iterator for the root node of the DOM adapter final int iter = cpg.addInterfaceMethodref(DOM_INTF, "getIterator", "()"+NODE_ITERATOR_SIG); il.append(new INVOKEINTERFACE(iter, 1)); }
Subsume result tree into ObjectType.
See Also:
  • translateTo.translateTo
/** * Subsume result tree into ObjectType. * * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo */
public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, ObjectType type) { methodGen.getInstructionList().append(NOP); }
Translates a result tree 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.
Params:
  • classGen – A BCEL class generator
  • methodGen – A BCEL method generator
  • type – An instance of BooleanType (any)
See Also:
/** * Translates a result tree 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. * * @param classGen A BCEL class generator * @param methodGen A BCEL method generator * @param type An instance of BooleanType (any) * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateToDesynthesized */
public FlowList translateToDesynthesized(ClassGenerator classGen, MethodGenerator methodGen, BooleanType type) { final InstructionList il = methodGen.getInstructionList(); translateTo(classGen, methodGen, Type.Boolean); return new FlowList(il.append(new IFEQ(null))); }
Translates a result tree to a Java type denoted by clazz. Expects a result tree on the stack and pushes an object of the appropriate type after coercion. Result trees are translated to W3C Node or W3C NodeList and the translation is done via node-set type.
Params:
  • classGen – A BCEL class generator
  • methodGen – A BCEL method generator
  • clazz – An reference to the Class to translate to
See Also:
/** * Translates a result tree to a Java type denoted by <code>clazz</code>. * Expects a result tree on the stack and pushes an object * of the appropriate type after coercion. Result trees are translated * to W3C Node or W3C NodeList and the translation is done * via node-set type. * * @param classGen A BCEL class generator * @param methodGen A BCEL method generator * @param clazz An reference to the Class to translate to * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo */
public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, Class<?> clazz) { final String className = clazz.getName(); final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); if (className.equals("org.w3c.dom.Node")) { translateTo(classGen, methodGen, Type.NodeSet); int index = cpg.addInterfaceMethodref(DOM_INTF, MAKE_NODE, MAKE_NODE_SIG2); il.append(new INVOKEINTERFACE(index, 2)); } else if (className.equals("org.w3c.dom.NodeList")) { translateTo(classGen, methodGen, Type.NodeSet); int index = cpg.addInterfaceMethodref(DOM_INTF, MAKE_NODE_LIST, MAKE_NODE_LIST_SIG2); il.append(new INVOKEINTERFACE(index, 2)); } else if (className.equals("java.lang.Object")) { il.append(NOP); } else if (className.equals("java.lang.String")) { translateTo(classGen, methodGen, Type.String); } 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.
/** * 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.
/** * Translates an object of this type to its unboxed representation. */
public void translateUnBox(ClassGenerator classGen, MethodGenerator methodGen) { methodGen.getInstructionList().append(NOP); }
Returns the class name of an internal type's external representation.
/** * Returns the class name of an internal type's external representation. */
public String getClassName() { return(DOM_INTF); } public Instruction LOAD(int slot) { return new ALOAD(slot); } public Instruction STORE(int slot) { return new ASTORE(slot); } }