001: /*
002: * Copyright 2001-2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: /*
017: * $Id: LiteralAttribute.java,v 1.9 2004/05/21 20:29:28 santiagopg Exp $
018: */
019:
020: package org.apache.xalan.xsltc.compiler;
021:
022: import org.apache.bcel.generic.ConstantPoolGen;
023: import org.apache.bcel.generic.InstructionList;
024: import org.apache.bcel.generic.PUSH;
025: import org.apache.xalan.xsltc.compiler.util.ClassGenerator;
026: import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
027: import org.apache.xalan.xsltc.compiler.util.Type;
028: import org.apache.xalan.xsltc.compiler.util.TypeCheckError;
029: import org.apache.xalan.xsltc.compiler.util.Util;
030:
031: import org.apache.xml.serializer.ElemDesc;
032: import org.apache.xml.serializer.SerializationHandler;
033:
034: /**
035: * @author Jacek Ambroziak
036: * @author Santiago Pericas-Geertsen
037: * @author Morten Jorgensen
038: */
039: final class LiteralAttribute extends Instruction {
040:
041: private final String _name; // Attribute name (incl. prefix)
042: private final AttributeValue _value; // Attribute value
043:
044: /**
045: * Creates a new literal attribute (but does not insert it into the AST).
046: * @param name the attribute name (incl. prefix) as a String.
047: * @param value the attribute value.
048: * @param parser the XSLT parser (wraps XPath parser).
049: */
050: public LiteralAttribute(String name, String value, Parser parser,
051: SyntaxTreeNode parent) {
052: _name = name;
053: setParent(parent);
054: _value = AttributeValue.create(this , value, parser);
055: }
056:
057: public void display(int indent) {
058: indent(indent);
059: Util.println("LiteralAttribute name=" + _name + " value="
060: + _value);
061: }
062:
063: public Type typeCheck(SymbolTable stable) throws TypeCheckError {
064: _value.typeCheck(stable);
065: typeCheckContents(stable);
066: return Type.Void;
067: }
068:
069: protected boolean contextDependent() {
070: return _value.contextDependent();
071: }
072:
073: public void translate(ClassGenerator classGen,
074: MethodGenerator methodGen) {
075: final ConstantPoolGen cpg = classGen.getConstantPool();
076: final InstructionList il = methodGen.getInstructionList();
077:
078: // push handler
079: il.append(methodGen.loadHandler());
080: // push attribute name - namespace prefix set by parent node
081: il.append(new PUSH(cpg, _name));
082: // push attribute value
083: _value.translate(classGen, methodGen);
084:
085: // Generate code that calls SerializationHandler.addUniqueAttribute()
086: // if all attributes are unique.
087: SyntaxTreeNode parent = getParent();
088: if (parent instanceof LiteralElement
089: && ((LiteralElement) parent).allAttributesUnique()) {
090:
091: int flags = 0;
092: boolean isHTMLAttrEmpty = false;
093: ElemDesc elemDesc = ((LiteralElement) parent).getElemDesc();
094:
095: // Set the HTML flags
096: if (elemDesc != null) {
097: if (elemDesc.isAttrFlagSet(_name, ElemDesc.ATTREMPTY)) {
098: flags = flags | SerializationHandler.HTML_ATTREMPTY;
099: isHTMLAttrEmpty = true;
100: } else if (elemDesc.isAttrFlagSet(_name,
101: ElemDesc.ATTRURL)) {
102: flags = flags | SerializationHandler.HTML_ATTRURL;
103: }
104: }
105:
106: if (_value instanceof SimpleAttributeValue) {
107: String attrValue = ((SimpleAttributeValue) _value)
108: .toString();
109:
110: if (!hasBadChars(attrValue) && !isHTMLAttrEmpty) {
111: flags = flags | SerializationHandler.NO_BAD_CHARS;
112: }
113: }
114:
115: il.append(new PUSH(cpg, flags));
116: il.append(methodGen.uniqueAttribute());
117: } else {
118: // call attribute
119: il.append(methodGen.attribute());
120: }
121: }
122:
123: /**
124: * Return true if at least one character in the String is considered to
125: * be a "bad" character. A bad character is one whose code is:
126: * less than 32 (a space),
127: * or greater than 126,
128: * or it is one of '<', '>', '&' or '\"'.
129: * This helps the serializer to decide whether the String needs to be escaped.
130: */
131: private boolean hasBadChars(String value) {
132: char[] chars = value.toCharArray();
133: int size = chars.length;
134: for (int i = 0; i < size; i++) {
135: char ch = chars[i];
136: if (ch < 32 || 126 < ch || ch == '<' || ch == '>'
137: || ch == '&' || ch == '\"')
138: return true;
139: }
140: return false;
141: }
142:
143: /**
144: * Return the name of the attribute
145: */
146: public String getName() {
147: return _name;
148: }
149:
150: /**
151: * Return the value of the attribute
152: */
153: public AttributeValue getValue() {
154: return _value;
155: }
156:
157: }
|