KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xalan > xsltc > compiler > Text


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 /*
17  * $Id: Text.java,v 1.17 2004/02/16 22:25:10 minchau Exp $
18  */

19
20 package org.apache.xalan.xsltc.compiler;
21
22 import org.apache.bcel.generic.ConstantPoolGen;
23 import org.apache.bcel.generic.GETSTATIC;
24 import org.apache.bcel.generic.INVOKEINTERFACE;
25 import org.apache.bcel.generic.InstructionList;
26 import org.apache.bcel.generic.PUSH;
27 import org.apache.xalan.xsltc.compiler.util.ClassGenerator;
28 import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
29 import org.apache.xalan.xsltc.compiler.util.Util;
30
31 /**
32  * @author Jacek Ambroziak
33  * @author Santiago Pericas-Geertsen
34  * @author Morten Jorgensen
35  */

36 final class Text extends Instruction {
37
38     private String JavaDoc _text;
39     private boolean _escaping = true;
40     private boolean _ignore = false;
41     private boolean _textElement = false;
42
43     /**
44      * Create a blank Text syntax tree node.
45      */

46     public Text() {
47     _textElement = true;
48     }
49
50     /**
51      * Create text syntax tree node.
52      * @param text is the text to put in the node.
53      */

54     public Text(String JavaDoc text) {
55     _text = text;
56     }
57
58     /**
59      * Returns the text wrapped inside this node
60      * @return The text wrapped inside this node
61      */

62     protected String JavaDoc getText() {
63     return _text;
64     }
65
66     /**
67      * Set the text for this node. Appends the given text to any already
68      * existing text (using string concatenation, so use only when needed).
69      * @param text is the text to wrap inside this node.
70      */

71     protected void setText(String JavaDoc text) {
72     if (_text == null)
73         _text = text;
74     else
75         _text = _text + text;
76     }
77
78     public void display(int indent) {
79     indent(indent);
80     Util.println("Text");
81     indent(indent + IndentIncrement);
82     Util.println(_text);
83     }
84         
85     public void parseContents(Parser parser) {
86         final String JavaDoc str = getAttribute("disable-output-escaping");
87     if ((str != null) && (str.equals("yes"))) _escaping = false;
88
89     parseChildren(parser);
90
91     if (_text == null) {
92         if (_textElement) {
93         _text = EMPTYSTRING;
94         }
95         else {
96         _ignore = true;
97         }
98     }
99     else if (_textElement) {
100         if (_text.length() == 0) _ignore = true;
101     }
102     else if (getParent() instanceof LiteralElement) {
103         LiteralElement element = (LiteralElement)getParent();
104         String JavaDoc space = element.getAttribute("xml:space");
105         if ((space == null) || (!space.equals("preserve")))
106         if (_text.trim().length() == 0) _ignore = true;
107     }
108     else {
109         if (_text.trim().length() == 0) _ignore = true;
110     }
111     }
112
113     public void ignore() {
114     _ignore = true;
115     }
116
117     public boolean isIgnore() {
118         return _ignore;
119     }
120     
121     public boolean isTextElement() {
122     return _textElement;
123     }
124
125     protected boolean contextDependent() {
126     return false;
127     }
128
129     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
130     final ConstantPoolGen cpg = classGen.getConstantPool();
131     final InstructionList il = methodGen.getInstructionList();
132
133     if (!_ignore) {
134         // Turn off character escaping if so is wanted.
135
final int esc = cpg.addInterfaceMethodref(OUTPUT_HANDLER,
136                               "setEscaping", "(Z)Z");
137         if (!_escaping) {
138         il.append(methodGen.loadHandler());
139         il.append(new PUSH(cpg, false));
140         il.append(new INVOKEINTERFACE(esc, 2));
141         }
142
143             il.append(methodGen.loadHandler());
144
145             // Call characters(String) or characters(char[],int,int), as
146
// appropriate.
147
if (!canLoadAsArrayOffsetLength()) {
148                 final int characters = cpg.addInterfaceMethodref(OUTPUT_HANDLER,
149                                                            "characters",
150                                                            "("+STRING_SIG+")V");
151                 il.append(new PUSH(cpg, _text));
152                 il.append(new INVOKEINTERFACE(characters, 2));
153             } else {
154                 final int characters = cpg.addInterfaceMethodref(OUTPUT_HANDLER,
155                                                                  "characters",
156                                                                  "([CII)V");
157                 loadAsArrayOffsetLength(classGen, methodGen);
158             il.append(new INVOKEINTERFACE(characters, 4));
159             }
160
161         // Restore character escaping setting to whatever it was.
162
// Note: setEscaping(bool) returns the original (old) value
163
if (!_escaping) {
164         il.append(methodGen.loadHandler());
165         il.append(SWAP);
166         il.append(new INVOKEINTERFACE(esc, 2));
167         il.append(POP);
168         }
169     }
170     translateContents(classGen, methodGen);
171     }
172
173     /**
174      * Check whether this Text node can be stored in a char[] in the translet.
175      * Calling this is precondition to calling loadAsArrayOffsetLength.
176      * @see #loadAsArrayOffsetLength(ClassGenerator,MethodGenerator)
177      * @return true if this Text node can be
178      */

179     public boolean canLoadAsArrayOffsetLength() {
180         // Magic number! 21845*3 == 65535. BCEL uses a DataOutputStream to
181
// serialize class files. The Java run-time places a limit on the size
182
// of String data written using a DataOutputStream - it cannot require
183
// more than 64KB when represented as UTF-8. The number of bytes
184
// required to represent a Java string as UTF-8 cannot be greater
185
// than three times the number of char's in the string, hence the
186
// check for 21845.
187

188         return (_text.length() <= 21845);
189     }
190
191     /**
192      * Generates code that loads the array that will contain the character
193      * data represented by this Text node, followed by the offset of the
194      * data from the start of the array, and then the length of the data.
195      *
196      * The pre-condition to calling this method is that
197      * canLoadAsArrayOffsetLength() returns true.
198      * @see #canLoadArrayOffsetLength()
199      */

200     public void loadAsArrayOffsetLength(ClassGenerator classGen,
201                                         MethodGenerator methodGen) {
202         final ConstantPoolGen cpg = classGen.getConstantPool();
203         final InstructionList il = methodGen.getInstructionList();
204         final XSLTC xsltc = classGen.getParser().getXSLTC();
205
206         // The XSLTC object keeps track of character data
207
// that is to be stored in char arrays.
208
final int offset = xsltc.addCharacterData(_text);
209         final int length = _text.length();
210         String JavaDoc charDataFieldName =
211             STATIC_CHAR_DATA_FIELD + (xsltc.getCharacterDataCount()-1);
212
213         il.append(new GETSTATIC(cpg.addFieldref(xsltc.getClassName(),
214                                        charDataFieldName,
215                                        STATIC_CHAR_DATA_FIELD_SIG)));
216         il.append(new PUSH(cpg, offset));
217         il.append(new PUSH(cpg, _text.length()));
218     }
219 }
220
Popular Tags