001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 /*
019 * $Id: CopyOf.java 468650 2006-10-28 07:03:30Z minchau $
020 */
021
022 package org.apache.xalan.xsltc.compiler;
023
024 import org.apache.bcel.generic.ConstantPoolGen;
025 import org.apache.bcel.generic.INVOKEINTERFACE;
026 import org.apache.bcel.generic.INVOKESTATIC;
027 import org.apache.bcel.generic.INVOKEVIRTUAL;
028 import org.apache.bcel.generic.InstructionList;
029 import org.apache.xalan.xsltc.compiler.util.ClassGenerator;
030 import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
031 import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
032 import org.apache.xalan.xsltc.compiler.util.NodeSetType;
033 import org.apache.xalan.xsltc.compiler.util.NodeType;
034 import org.apache.xalan.xsltc.compiler.util.ReferenceType;
035 import org.apache.xalan.xsltc.compiler.util.ResultTreeType;
036 import org.apache.xalan.xsltc.compiler.util.Type;
037 import org.apache.xalan.xsltc.compiler.util.TypeCheckError;
038 import org.apache.xalan.xsltc.compiler.util.Util;
039
040 /**
041 * @author Jacek Ambroziak
042 * @author Santiago Pericas-Geertsen
043 */
044 final class CopyOf extends Instruction {
045 private Expression _select;
046
047 public void display(int indent) {
048 indent(indent);
049 Util.println("CopyOf");
050 indent(indent + IndentIncrement);
051 Util.println("select " + _select.toString());
052 }
053
054 public void parseContents(Parser parser) {
055 _select = parser.parseExpression(this, "select", null);
056 // make sure required attribute(s) have been set
057 if (_select.isDummy()) {
058 reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "select");
059 return;
060 }
061 }
062
063 public Type typeCheck(SymbolTable stable) throws TypeCheckError {
064 final Type tselect = _select.typeCheck(stable);
065 if (tselect instanceof NodeType ||
066 tselect instanceof NodeSetType ||
067 tselect instanceof ReferenceType ||
068 tselect instanceof ResultTreeType) {
069 // falls through
070 }
071 else {
072 _select = new CastExpr(_select, Type.String);
073 }
074 return Type.Void;
075 }
076
077 public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
078 final ConstantPoolGen cpg = classGen.getConstantPool();
079 final InstructionList il = methodGen.getInstructionList();
080 final Type tselect = _select.getType();
081
082 final String CPY1_SIG = "("+NODE_ITERATOR_SIG+TRANSLET_OUTPUT_SIG+")V";
083 final int cpy1 = cpg.addInterfaceMethodref(DOM_INTF, "copy", CPY1_SIG);
084
085 final String CPY2_SIG = "("+NODE_SIG+TRANSLET_OUTPUT_SIG+")V";
086 final int cpy2 = cpg.addInterfaceMethodref(DOM_INTF, "copy", CPY2_SIG);
087
088 final String getDoc_SIG = "()"+NODE_SIG;
089 final int getDoc = cpg.addInterfaceMethodref(DOM_INTF, "getDocument", getDoc_SIG);
090
091
092 if (tselect instanceof NodeSetType) {
093 il.append(methodGen.loadDOM());
094
095 // push NodeIterator
096 _select.translate(classGen, methodGen);
097 _select.startIterator(classGen, methodGen);
098
099 // call copy from the DOM 'library'
100 il.append(methodGen.loadHandler());
101 il.append(new INVOKEINTERFACE(cpy1, 3));
102 }
103 else if (tselect instanceof NodeType) {
104 il.append(methodGen.loadDOM());
105 _select.translate(classGen, methodGen);
106 il.append(methodGen.loadHandler());
107 il.append(new INVOKEINTERFACE(cpy2, 3));
108 }
109 else if (tselect instanceof ResultTreeType) {
110 _select.translate(classGen, methodGen);
111 // We want the whole tree, so we start with the root node
112 il.append(DUP); //need a pointer to the DOM ;
113 il.append(new INVOKEINTERFACE(getDoc,1)); //ICONST_0);
114 il.append(methodGen.loadHandler());
115 il.append(new INVOKEINTERFACE(cpy2, 3));
116 }
117 else if (tselect instanceof ReferenceType) {
118 _select.translate(classGen, methodGen);
119 il.append(methodGen.loadHandler());
120 il.append(methodGen.loadCurrentNode());
121 il.append(methodGen.loadDOM());
122 final int copy = cpg.addMethodref(BASIS_LIBRARY_CLASS, "copy",
123 "("
124 + OBJECT_SIG
125 + TRANSLET_OUTPUT_SIG
126 + NODE_SIG
127 + DOM_INTF_SIG
128 + ")V");
129 il.append(new INVOKESTATIC(copy));
130 }
131 else {
132 il.append(classGen.loadTranslet());
133 _select.translate(classGen, methodGen);
134 il.append(methodGen.loadHandler());
135 il.append(new INVOKEVIRTUAL(cpg.addMethodref(TRANSLET_CLASS,
136 CHARACTERSW,
137 CHARACTERSW_SIG)));
138 }
139
140 }
141 }