NodeSetType.java revision 628:2bfaf29cc90b
184124Sdfr/* 284124Sdfr * reserved comment block 384124Sdfr * DO NOT REMOVE OR ALTER! 484124Sdfr */ 584124Sdfr/* 684124Sdfr * Copyright 2001-2004 The Apache Software Foundation. 784124Sdfr * 884124Sdfr * Licensed under the Apache License, Version 2.0 (the "License"); 984124Sdfr * you may not use this file except in compliance with the License. 1084124Sdfr * You may obtain a copy of the License at 1184124Sdfr * 1284124Sdfr * http://www.apache.org/licenses/LICENSE-2.0 1384124Sdfr * 1484124Sdfr * Unless required by applicable law or agreed to in writing, software 1584124Sdfr * distributed under the License is distributed on an "AS IS" BASIS, 1684124Sdfr * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1784124Sdfr * See the License for the specific language governing permissions and 1884124Sdfr * limitations under the License. 1984124Sdfr */ 2084124Sdfr/* 2184124Sdfr * $Id: NodeSetType.java,v 1.2.4.1 2005/09/05 11:21:45 pvedula Exp $ 2284124Sdfr */ 2384124Sdfr 2484124Sdfrpackage com.sun.org.apache.xalan.internal.xsltc.compiler.util; 2584124Sdfr 2684124Sdfrimport com.sun.org.apache.bcel.internal.generic.ALOAD; 2784124Sdfrimport com.sun.org.apache.bcel.internal.generic.ASTORE; 2884124Sdfrimport com.sun.org.apache.bcel.internal.generic.BranchHandle; 2984124Sdfrimport com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; 3084124Sdfrimport com.sun.org.apache.bcel.internal.generic.GOTO; 3184124Sdfrimport com.sun.org.apache.bcel.internal.generic.IFLT; 3284124Sdfrimport com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE; 3384124Sdfrimport com.sun.org.apache.bcel.internal.generic.INVOKESTATIC; 3484124Sdfrimport com.sun.org.apache.bcel.internal.generic.Instruction; 3584124Sdfrimport com.sun.org.apache.bcel.internal.generic.InstructionList; 3684124Sdfrimport com.sun.org.apache.bcel.internal.generic.PUSH; 3784124Sdfrimport com.sun.org.apache.xalan.internal.xsltc.compiler.Constants; 3884124Sdfrimport com.sun.org.apache.xalan.internal.xsltc.compiler.FlowList; 3984124Sdfr 4084124Sdfr/** 4184124Sdfr * @author Jacek Ambroziak 4284124Sdfr * @author Santiago Pericas-Geertsen 4384124Sdfr */ 4484124Sdfrpublic final class NodeSetType extends Type { 4584124Sdfr protected NodeSetType() {} 4684124Sdfr 4784124Sdfr public String toString() { 4884124Sdfr return "node-set"; 4984124Sdfr } 5084124Sdfr 5184124Sdfr public boolean identicalTo(Type other) { 5284124Sdfr return this == other; 5384124Sdfr } 5484124Sdfr 5584124Sdfr public String toSignature() { 56119970Smarcel return NODE_ITERATOR_SIG; 5784124Sdfr } 58119970Smarcel 5984124Sdfr public com.sun.org.apache.bcel.internal.generic.Type toJCType() { 60119970Smarcel return new com.sun.org.apache.bcel.internal.generic.ObjectType(NODE_ITERATOR); 61119970Smarcel } 6284124Sdfr 6384541Sdfr /** 6484124Sdfr * Translates a node-set into an object of internal type 6584124Sdfr * <code>type</code>. The translation to int is undefined 6684124Sdfr * since node-sets are always converted to 6784124Sdfr * reals in arithmetic expressions. 6884124Sdfr * 6984124Sdfr * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 7084124Sdfr */ 7184124Sdfr public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 7284124Sdfr Type type) { 7384124Sdfr if (type == Type.String) { 7484124Sdfr translateTo(classGen, methodGen, (StringType) type); 7584124Sdfr } 7684124Sdfr else if (type == Type.Boolean) { 7784124Sdfr translateTo(classGen, methodGen, (BooleanType) type); 7884124Sdfr } 7984124Sdfr else if (type == Type.Real) { 8084124Sdfr translateTo(classGen, methodGen, (RealType) type); 8184124Sdfr } 8284124Sdfr else if (type == Type.Node) { 8384124Sdfr translateTo(classGen, methodGen, (NodeType) type); 8484124Sdfr } 8584124Sdfr else if (type == Type.Reference) { 8684124Sdfr translateTo(classGen, methodGen, (ReferenceType) type); 8784124Sdfr } 8884124Sdfr else if (type == Type.Object) { 8984124Sdfr translateTo(classGen, methodGen, (ObjectType) type); 9084124Sdfr } 9184124Sdfr else { 9284124Sdfr ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 9384124Sdfr toString(), type.toString()); 9484124Sdfr classGen.getParser().reportError(Constants.FATAL, err); 9584124Sdfr } 9684124Sdfr } 9784124Sdfr 9884124Sdfr /** 99119970Smarcel * Translates an external Java Class into an internal type. 100119970Smarcel * Expects the Java object on the stack, pushes the internal type 10184124Sdfr */ 102119970Smarcel public void translateFrom(ClassGenerator classGen, 103119970Smarcel MethodGenerator methodGen, Class clazz) 10484124Sdfr { 10584124Sdfr 10684124Sdfr InstructionList il = methodGen.getInstructionList(); 10784124Sdfr ConstantPoolGen cpg = classGen.getConstantPool(); 10884124Sdfr if (clazz.getName().equals("org.w3c.dom.NodeList")) { 10984124Sdfr // w3c NodeList is on the stack from the external Java function call. 11084124Sdfr // call BasisFunction to consume NodeList and leave Iterator on 11184124Sdfr // the stack. 11284124Sdfr il.append(classGen.loadTranslet()); // push translet onto stack 11384124Sdfr il.append(methodGen.loadDOM()); // push DOM onto stack 11484124Sdfr final int convert = cpg.addMethodref(BASIS_LIBRARY_CLASS, 11584124Sdfr "nodeList2Iterator", 11684124Sdfr "(" 11784124Sdfr + "Lorg/w3c/dom/NodeList;" 11884124Sdfr + TRANSLET_INTF_SIG 11984124Sdfr + DOM_INTF_SIG 12084124Sdfr + ")" + NODE_ITERATOR_SIG ); 12184124Sdfr il.append(new INVOKESTATIC(convert)); 12284124Sdfr } 12384124Sdfr else if (clazz.getName().equals("org.w3c.dom.Node")) { 12484124Sdfr // w3c Node is on the stack from the external Java function call. 12584124Sdfr // call BasisLibrary.node2Iterator() to consume Node and leave 12684124Sdfr // Iterator on the stack. 12784124Sdfr il.append(classGen.loadTranslet()); // push translet onto stack 128119970Smarcel il.append(methodGen.loadDOM()); // push DOM onto stack 12984124Sdfr final int convert = cpg.addMethodref(BASIS_LIBRARY_CLASS, 13084124Sdfr "node2Iterator", 13184124Sdfr "(" 13284124Sdfr + "Lorg/w3c/dom/Node;" 13384124Sdfr + TRANSLET_INTF_SIG 13484124Sdfr + DOM_INTF_SIG 13584124Sdfr + ")" + NODE_ITERATOR_SIG ); 13684124Sdfr il.append(new INVOKESTATIC(convert)); 13784124Sdfr } 13884124Sdfr else { 13984124Sdfr ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 14084124Sdfr toString(), clazz.getName()); 14184124Sdfr classGen.getParser().reportError(Constants.FATAL, err); 14284124Sdfr } 14384124Sdfr } 14484124Sdfr 14584124Sdfr 14684124Sdfr /** 14784124Sdfr * Translates a node-set into a synthesized boolean. 14884124Sdfr * The boolean value of a node-set is "true" if non-empty 14984124Sdfr * and "false" otherwise. Notice that the 15084124Sdfr * function getFirstNode() is called in translateToDesynthesized(). 15184124Sdfr * 15284124Sdfr * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 15384124Sdfr */ 15484124Sdfr public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 15584124Sdfr BooleanType type) { 15684124Sdfr final InstructionList il = methodGen.getInstructionList(); 15784124Sdfr FlowList falsel = translateToDesynthesized(classGen, methodGen, type); 15884124Sdfr il.append(ICONST_1); 15984124Sdfr final BranchHandle truec = il.append(new GOTO(null)); 16084124Sdfr falsel.backPatch(il.append(ICONST_0)); 16184124Sdfr truec.setTarget(il.append(NOP)); 16284124Sdfr } 16384124Sdfr 16484124Sdfr /** 16584124Sdfr * Translates a node-set into a string. The string value of a node-set is 16684124Sdfr * value of its first element. 16784124Sdfr * 16884124Sdfr * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 16984124Sdfr */ 17084124Sdfr public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 17184124Sdfr StringType type) { 172100398Speter final InstructionList il = methodGen.getInstructionList(); 17384124Sdfr getFirstNode(classGen, methodGen); 17484124Sdfr il.append(DUP); 17584124Sdfr final BranchHandle falsec = il.append(new IFLT(null)); 17684124Sdfr Type.Node.translateTo(classGen, methodGen, type); 17784124Sdfr final BranchHandle truec = il.append(new GOTO(null)); 17884124Sdfr falsec.setTarget(il.append(POP)); 17984124Sdfr il.append(new PUSH(classGen.getConstantPool(), "")); 18084124Sdfr truec.setTarget(il.append(NOP)); 18184124Sdfr } 18284124Sdfr 18384124Sdfr /** 18484124Sdfr * Expects a node-set on the stack and pushes a real. 18584124Sdfr * First the node-set is converted to string, and from string to real. 18684124Sdfr * 18784124Sdfr * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 18884124Sdfr */ 18984124Sdfr public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 19084124Sdfr RealType type) { 19184124Sdfr translateTo(classGen, methodGen, Type.String); 19284124Sdfr Type.String.translateTo(classGen, methodGen, Type.Real); 19384124Sdfr } 19484124Sdfr 19584124Sdfr /** 19684124Sdfr * Expects a node-set on the stack and pushes a node. 19784124Sdfr * 19884124Sdfr * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 19984124Sdfr */ 20084124Sdfr public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 20184124Sdfr NodeType type) { 20284124Sdfr getFirstNode(classGen, methodGen); 20384124Sdfr } 20484124Sdfr 20584124Sdfr /** 20684124Sdfr * Subsume node-set into ObjectType. 20784124Sdfr * 20884124Sdfr * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 20984124Sdfr */ 21084124Sdfr public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 21184124Sdfr ObjectType type) { 21284124Sdfr methodGen.getInstructionList().append(NOP); 21384124Sdfr } 21484124Sdfr 21584124Sdfr /** 21684124Sdfr * Translates a node-set into a non-synthesized boolean. It does not 21784124Sdfr * push a 0 or a 1 but instead returns branchhandle list to be appended 21884124Sdfr * to the false list. 21984124Sdfr * 22084541Sdfr * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateToDesynthesized 22184541Sdfr */ 22284541Sdfr public FlowList translateToDesynthesized(ClassGenerator classGen, 22384541Sdfr MethodGenerator methodGen, 22484541Sdfr BooleanType type) { 22584541Sdfr final InstructionList il = methodGen.getInstructionList(); 22684124Sdfr getFirstNode(classGen, methodGen); 22784124Sdfr return new FlowList(il.append(new IFLT(null))); 22884124Sdfr } 22984124Sdfr 23084124Sdfr /** 23184124Sdfr * Expects a node-set on the stack and pushes a boxed node-set. 23284124Sdfr * Node sets are already boxed so the translation is just a NOP. 23384124Sdfr * 23484124Sdfr * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 23584124Sdfr */ 23684124Sdfr public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 23784124Sdfr ReferenceType type) { 23884124Sdfr methodGen.getInstructionList().append(NOP); 23984124Sdfr } 24084124Sdfr 24184124Sdfr /** 24284124Sdfr * Translates a node-set into the Java type denoted by <code>clazz</code>. 24384124Sdfr * Expects a node-set on the stack and pushes an object of the appropriate 24484124Sdfr * type after coercion. 24584124Sdfr */ 24684124Sdfr public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 24784124Sdfr Class clazz) { 24884124Sdfr final ConstantPoolGen cpg = classGen.getConstantPool(); 24984124Sdfr final InstructionList il = methodGen.getInstructionList(); 25084124Sdfr final String className = clazz.getName(); 25184124Sdfr 25284124Sdfr il.append(methodGen.loadDOM()); 25384124Sdfr il.append(SWAP); 25484124Sdfr 25584124Sdfr if (className.equals("org.w3c.dom.Node")) { 25684124Sdfr int index = cpg.addInterfaceMethodref(DOM_INTF, 25784124Sdfr MAKE_NODE, 25884124Sdfr MAKE_NODE_SIG2); 25984124Sdfr il.append(new INVOKEINTERFACE(index, 2)); 26084124Sdfr } 26184124Sdfr else if (className.equals("org.w3c.dom.NodeList") || 26284124Sdfr className.equals("java.lang.Object")) { 26384124Sdfr int index = cpg.addInterfaceMethodref(DOM_INTF, 26484124Sdfr MAKE_NODE_LIST, 26584124Sdfr MAKE_NODE_LIST_SIG2); 26684124Sdfr il.append(new INVOKEINTERFACE(index, 2)); 26784124Sdfr } 26884124Sdfr else if (className.equals("java.lang.String")) { 26984124Sdfr int next = cpg.addInterfaceMethodref(NODE_ITERATOR, 27084124Sdfr "next", "()I"); 27184124Sdfr int index = cpg.addInterfaceMethodref(DOM_INTF, 27284124Sdfr GET_NODE_VALUE, 27384124Sdfr "(I)"+STRING_SIG); 27484124Sdfr 27584124Sdfr // Get next node from the iterator 27684124Sdfr il.append(new INVOKEINTERFACE(next, 1)); 27784124Sdfr // Get the node's string value (from the DOM) 27884124Sdfr il.append(new INVOKEINTERFACE(index, 2)); 27984124Sdfr 28084124Sdfr } 28184124Sdfr else { 28284124Sdfr ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 28384124Sdfr toString(), className); 28484124Sdfr classGen.getParser().reportError(Constants.FATAL, err); 28584124Sdfr } 28684124Sdfr } 28784124Sdfr 28884124Sdfr /** 28984124Sdfr * Some type conversions require gettting the first node from the node-set. 29084124Sdfr * This function is defined to avoid code repetition. 29184124Sdfr */ 29284124Sdfr private void getFirstNode(ClassGenerator classGen, MethodGenerator methodGen) { 29384124Sdfr final ConstantPoolGen cpg = classGen.getConstantPool(); 29484124Sdfr final InstructionList il = methodGen.getInstructionList(); 29584124Sdfr il.append(new INVOKEINTERFACE(cpg.addInterfaceMethodref(NODE_ITERATOR, 29684124Sdfr NEXT, 29784124Sdfr NEXT_SIG), 1)); 29884124Sdfr } 29984124Sdfr 30084124Sdfr /** 30184124Sdfr * Translates an object of this type to its boxed representation. 30284124Sdfr */ 30384124Sdfr public void translateBox(ClassGenerator classGen, 30484124Sdfr MethodGenerator methodGen) { 30584124Sdfr translateTo(classGen, methodGen, Type.Reference); 30684124Sdfr } 30784124Sdfr 30884124Sdfr /** 30984124Sdfr * Translates an object of this type to its unboxed representation. 31084124Sdfr */ 31184124Sdfr public void translateUnBox(ClassGenerator classGen, 31284124Sdfr MethodGenerator methodGen) { 31384124Sdfr methodGen.getInstructionList().append(NOP); 31484124Sdfr } 31584124Sdfr 31684124Sdfr /** 31784124Sdfr * Returns the class name of an internal type's external representation. 31884124Sdfr */ 31984124Sdfr public String getClassName() { 32084124Sdfr return(NODE_ITERATOR); 32184124Sdfr } 32284124Sdfr 32384124Sdfr 32484124Sdfr public Instruction LOAD(int slot) { 32584124Sdfr return new ALOAD(slot); 32684124Sdfr } 32784124Sdfr 32884124Sdfr public Instruction STORE(int slot) { 32984124Sdfr return new ASTORE(slot); 33084124Sdfr } 33184124Sdfr} 33284124Sdfr