AttributeSet.java revision 628:2bfaf29cc90b
1/* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5/* 6 * Copyright 2001-2004 The Apache Software Foundation. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20/* 21 * $Id: AttributeSet.java,v 1.5 2005/09/28 13:48:04 pvedula Exp $ 22 */ 23 24package com.sun.org.apache.xalan.internal.xsltc.compiler; 25 26import java.util.Enumeration; 27import java.util.Vector; 28 29import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; 30import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL; 31import com.sun.org.apache.bcel.internal.generic.InstructionList; 32import com.sun.org.apache.xalan.internal.xsltc.compiler.util.AttributeSetMethodGenerator; 33import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; 34import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; 35import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; 36import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; 37import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError; 38import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util; 39import com.sun.org.apache.xml.internal.utils.XML11Char; 40 41/** 42 * @author Jacek Ambroziak 43 * @author Santiago Pericas-Geertsen 44 * @author Morten Jorgensen 45 */ 46final class AttributeSet extends TopLevelElement { 47 48 // This prefix is used for the method name of attribute set methods 49 private static final String AttributeSetPrefix = "$as$"; 50 51 // Element contents 52 private QName _name; 53 private UseAttributeSets _useSets; 54 private AttributeSet _mergeSet; 55 private String _method; 56 private boolean _ignore = false; 57 58 /** 59 * Returns the QName of this attribute set 60 */ 61 public QName getName() { 62 return _name; 63 } 64 65 /** 66 * Returns the method name of this attribute set. This method name is 67 * generated by the compiler (XSLTC) 68 */ 69 public String getMethodName() { 70 return _method; 71 } 72 73 /** 74 * Call this method to prevent a method for being compiled for this set. 75 * This is used in case several <xsl:attribute-set...> elements constitute 76 * a single set (with one name). The last element will merge itself with 77 * any previous set(s) with the same name and disable the other set(s). 78 */ 79 public void ignore() { 80 _ignore = true; 81 } 82 83 /** 84 * Parse the contents of this attribute set. Recognised attributes are 85 * "name" (required) and "use-attribute-sets" (optional). 86 */ 87 public void parseContents(Parser parser) { 88 89 // Get this attribute set's name 90 final String name = getAttribute("name"); 91 92 if (!XML11Char.isXML11ValidQName(name)) { 93 ErrorMsg err = new ErrorMsg(ErrorMsg.INVALID_QNAME_ERR, name, this); 94 parser.reportError(Constants.ERROR, err); 95 } 96 _name = parser.getQNameIgnoreDefaultNs(name); 97 if ((_name == null) || (_name.equals(EMPTYSTRING))) { 98 ErrorMsg msg = new ErrorMsg(ErrorMsg.UNNAMED_ATTRIBSET_ERR, this); 99 parser.reportError(Constants.ERROR, msg); 100 } 101 102 // Get any included attribute sets (similar to inheritance...) 103 final String useSets = getAttribute("use-attribute-sets"); 104 if (useSets.length() > 0) { 105 if (!Util.isValidQNames(useSets)) { 106 ErrorMsg err = new ErrorMsg(ErrorMsg.INVALID_QNAME_ERR, useSets, this); 107 parser.reportError(Constants.ERROR, err); 108 } 109 _useSets = new UseAttributeSets(useSets, parser); 110 } 111 112 // Parse the contents of this node. All child elements must be 113 // <xsl:attribute> elements. Other elements cause an error. 114 final Vector contents = getContents(); 115 final int count = contents.size(); 116 for (int i=0; i<count; i++) { 117 SyntaxTreeNode child = (SyntaxTreeNode)contents.elementAt(i); 118 if (child instanceof XslAttribute) { 119 parser.getSymbolTable().setCurrentNode(child); 120 child.parseContents(parser); 121 } 122 else if (child instanceof Text) { 123 // ignore 124 } 125 else { 126 ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_CHILD_ERR, this); 127 parser.reportError(Constants.ERROR, msg); 128 } 129 } 130 131 // Point the symbol table back at us... 132 parser.getSymbolTable().setCurrentNode(this); 133 } 134 135 /** 136 * Type check the contents of this element 137 */ 138 public Type typeCheck(SymbolTable stable) throws TypeCheckError { 139 140 if (_ignore) return (Type.Void); 141 142 // _mergeSet Point to any previous definition of this attribute set 143 _mergeSet = stable.addAttributeSet(this); 144 145 _method = AttributeSetPrefix + getXSLTC().nextAttributeSetSerial(); 146 147 if (_useSets != null) _useSets.typeCheck(stable); 148 typeCheckContents(stable); 149 return Type.Void; 150 } 151 152 /** 153 * Compile a method that outputs the attributes in this set 154 */ 155 public void translate(ClassGenerator classGen, MethodGenerator methodGen) { 156 157 if (_ignore) return; 158 159 // Create a new method generator for an attribute set method 160 methodGen = new AttributeSetMethodGenerator(_method, classGen); 161 162 // Generate a reference to previous attribute-set definitions with the 163 // same name first. Those later in the stylesheet take precedence. 164 if (_mergeSet != null) { 165 final ConstantPoolGen cpg = classGen.getConstantPool(); 166 final InstructionList il = methodGen.getInstructionList(); 167 final String methodName = _mergeSet.getMethodName(); 168 169 il.append(classGen.loadTranslet()); 170 il.append(methodGen.loadDOM()); 171 il.append(methodGen.loadIterator()); 172 il.append(methodGen.loadHandler()); 173 il.append(methodGen.loadCurrentNode()); 174 final int method = cpg.addMethodref(classGen.getClassName(), 175 methodName, ATTR_SET_SIG); 176 il.append(new INVOKESPECIAL(method)); 177 } 178 179 // Translate other used attribute sets first, as local attributes 180 // take precedence (last attributes overrides first) 181 if (_useSets != null) _useSets.translate(classGen, methodGen); 182 183 // Translate all local attributes 184 final Enumeration attributes = elements(); 185 while (attributes.hasMoreElements()) { 186 SyntaxTreeNode element = (SyntaxTreeNode)attributes.nextElement(); 187 if (element instanceof XslAttribute) { 188 final XslAttribute attribute = (XslAttribute)element; 189 attribute.translate(classGen, methodGen); 190 } 191 } 192 final InstructionList il = methodGen.getInstructionList(); 193 il.append(RETURN); 194 195 classGen.addMethod(methodGen); 196 } 197 198 public String toString() { 199 StringBuffer buf = new StringBuffer("attribute-set: "); 200 // Translate all local attributes 201 final Enumeration attributes = elements(); 202 while (attributes.hasMoreElements()) { 203 final XslAttribute attribute = 204 (XslAttribute)attributes.nextElement(); 205 buf.append(attribute); 206 } 207 return(buf.toString()); 208 } 209} 210