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: ElemUse.java 476466 2006-11-18 08:22:31Z minchau $
020 */
021 package org.apache.xalan.templates;
022
023 import java.util.Vector;
024
025 import javax.xml.transform.TransformerException;
026
027 import org.apache.xalan.res.XSLMessages;
028 import org.apache.xalan.res.XSLTErrorResources;
029 import org.apache.xalan.transformer.TransformerImpl;
030 import org.apache.xml.utils.QName;
031
032 /**
033 * Implement xsl:use.
034 * This acts as a superclass for ElemCopy, ElemAttributeSet,
035 * ElemElement, and ElemLiteralResult, on order to implement
036 * shared behavior the use-attribute-sets attribute.
037 * @see <a href="http://www.w3.org/TR/xslt#attribute-sets">attribute-sets in XSLT Specification</a>
038 * @xsl.usage advanced
039 */
040 public class ElemUse extends ElemTemplateElement
041 {
042 static final long serialVersionUID = 5830057200289299736L;
043
044 /**
045 * The value of the "use-attribute-sets" attribute.
046 * @serial
047 */
048 private QName m_attributeSetsNames[] = null;
049
050 /**
051 * Set the "use-attribute-sets" attribute.
052 * Attribute sets are used by specifying a use-attribute-sets
053 * attribute on xsl:element, xsl:copy (see [7.5 Copying]) or
054 * xsl:attribute-set elements. The value of the use-attribute-sets
055 * attribute is a whitespace-separated list of names of attribute
056 * sets. Each name is specified as a QName, which is expanded as
057 * described in [2.4 Qualified Names].
058 *
059 * @param v The value to set for the "use-attribute-sets" attribute.
060 */
061 public void setUseAttributeSets(Vector v)
062 {
063
064 int n = v.size();
065
066 m_attributeSetsNames = new QName[n];
067
068 for (int i = 0; i < n; i++)
069 {
070 m_attributeSetsNames[i] = (QName) v.elementAt(i);
071 }
072 }
073
074 /**
075 * Set the "use-attribute-sets" attribute.
076 * Attribute sets are used by specifying a use-attribute-sets
077 * attribute on xsl:element, xsl:copy (see [7.5 Copying]) or
078 * xsl:attribute-set elements. The value of the use-attribute-sets
079 * attribute is a whitespace-separated list of names of attribute
080 * sets. Each name is specified as a QName, which is expanded as
081 * described in [2.4 Qualified Names].
082 *
083 * @param v The value to set for the "use-attribute-sets" attribute.
084 */
085 public void setUseAttributeSets(QName[] v)
086 {
087 m_attributeSetsNames = v;
088 }
089
090 /**
091 * Get the "use-attribute-sets" attribute.
092 * Attribute sets are used by specifying a use-attribute-sets
093 * attribute on xsl:element, xsl:copy (see [7.5 Copying]) or
094 * xsl:attribute-set elements, or a xsl:use-attribute-sets attribute on
095 * Literal Result Elements.
096 * The value of the use-attribute-sets
097 * attribute is a whitespace-separated list of names of attribute
098 * sets. Each name is specified as a QName, which is expanded as
099 * described in [2.4 Qualified Names].
100 *
101 * @return The value of the "use-attribute-sets" attribute.
102 */
103 public QName[] getUseAttributeSets()
104 {
105 return m_attributeSetsNames;
106 }
107
108 /**
109 * Add the attributes from the named attribute sets to the attribute list.
110 * TODO: Error handling for: "It is an error if there are two attribute sets
111 * with the same expanded-name and with equal import precedence and that both
112 * contain the same attribute unless there is a definition of the attribute
113 * set with higher import precedence that also contains the attribute."
114 *
115 * @param transformer non-null reference to the the current transform-time state.
116 * @param stylesheet The owning root stylesheet
117 *
118 * @throws TransformerException
119 */
120 public void applyAttrSets(
121 TransformerImpl transformer, StylesheetRoot stylesheet)
122 throws TransformerException
123 {
124 applyAttrSets(transformer, stylesheet, m_attributeSetsNames);
125 }
126
127 /**
128 * Add the attributes from the named attribute sets to the attribute list.
129 * TODO: Error handling for: "It is an error if there are two attribute sets
130 * with the same expanded-name and with equal import precedence and that both
131 * contain the same attribute unless there is a definition of the attribute
132 * set with higher import precedence that also contains the attribute."
133 *
134 * @param transformer non-null reference to the the current transform-time state.
135 * @param stylesheet The owning root stylesheet
136 * @param attributeSetsNames List of attribute sets names to apply
137 *
138 * @throws TransformerException
139 */
140 private void applyAttrSets(
141 TransformerImpl transformer, StylesheetRoot stylesheet, QName attributeSetsNames[])
142 throws TransformerException
143 {
144
145 if (null != attributeSetsNames)
146 {
147 int nNames = attributeSetsNames.length;
148
149 for (int i = 0; i < nNames; i++)
150 {
151 QName qname = attributeSetsNames[i];
152 java.util.List attrSets = stylesheet.getAttributeSetComposed(qname);
153
154 if (null != attrSets)
155 {
156 int nSets = attrSets.size();
157
158 // Highest priority attribute set will be at the top,
159 // so process it last.
160 for (int k = nSets-1; k >= 0 ; k--)
161 {
162 ElemAttributeSet attrSet =
163 (ElemAttributeSet) attrSets.get(k);
164
165 attrSet.execute(transformer);
166 }
167 }
168 else
169 {
170 throw new TransformerException(
171 XSLMessages.createMessage(XSLTErrorResources.ER_NO_ATTRIB_SET,
172 new Object[] {qname}),this);
173 }
174 }
175 }
176 }
177
178 /**
179 * Copy attributes specified by use-attribute-sets to the result tree.
180 * Specifying a use-attribute-sets attribute is equivalent to adding
181 * xsl:attribute elements for each of the attributes in each of the
182 * named attribute sets to the beginning of the content of the element
183 * with the use-attribute-sets attribute, in the same order in which
184 * the names of the attribute sets are specified in the use-attribute-sets
185 * attribute. It is an error if use of use-attribute-sets attributes
186 * on xsl:attribute-set elements causes an attribute set to directly
187 * or indirectly use itself.
188 *
189 * @param transformer non-null reference to the the current transform-time state.
190 *
191 * @throws TransformerException
192 */
193 public void execute(
194 TransformerImpl transformer)
195 throws TransformerException
196 {
197
198 if (null != m_attributeSetsNames)
199 {
200 applyAttrSets(transformer, getStylesheetRoot(),
201 m_attributeSetsNames);
202 }
203
204 }
205 }