1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the  "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *     http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18/*
19 * $Id: ElemUse.java 476466 2006-11-18 08:22:31Z minchau $
20 */
21package org.apache.xalan.templates;
22
23import java.util.Vector;
24
25import javax.xml.transform.TransformerException;
26
27import org.apache.xalan.res.XSLMessages;
28import org.apache.xalan.res.XSLTErrorResources;
29import org.apache.xalan.transformer.TransformerImpl;
30import org.apache.xml.utils.QName;
31
32/**
33 * Implement xsl:use.
34 * This acts as a superclass for ElemCopy, ElemAttributeSet,
35 * ElemElement, and ElemLiteralResult, on order to implement
36 * shared behavior the use-attribute-sets attribute.
37 * @see <a href="http://www.w3.org/TR/xslt#attribute-sets">attribute-sets in XSLT Specification</a>
38 * @xsl.usage advanced
39 */
40public class ElemUse extends ElemTemplateElement
41{
42    static final long serialVersionUID = 5830057200289299736L;
43
44  /**
45   * The value of the "use-attribute-sets" attribute.
46   * @serial
47   */
48  private QName m_attributeSetsNames[] = null;
49
50  /**
51   * Set the "use-attribute-sets" attribute.
52   * Attribute sets are used by specifying a use-attribute-sets
53   * attribute on xsl:element, xsl:copy (see [7.5 Copying]) or
54   * xsl:attribute-set elements. The value of the use-attribute-sets
55   * attribute is a whitespace-separated list of names of attribute
56   * sets. Each name is specified as a QName, which is expanded as
57   * described in [2.4 Qualified Names].
58   *
59   * @param v The value to set for the "use-attribute-sets" attribute.
60   */
61  public void setUseAttributeSets(Vector v)
62  {
63
64    int n = v.size();
65
66    m_attributeSetsNames = new QName[n];
67
68    for (int i = 0; i < n; i++)
69    {
70      m_attributeSetsNames[i] = (QName) v.elementAt(i);
71    }
72  }
73
74  /**
75   * Set the "use-attribute-sets" attribute.
76   * Attribute sets are used by specifying a use-attribute-sets
77   * attribute on xsl:element, xsl:copy (see [7.5 Copying]) or
78   * xsl:attribute-set elements. The value of the use-attribute-sets
79   * attribute is a whitespace-separated list of names of attribute
80   * sets. Each name is specified as a QName, which is expanded as
81   * described in [2.4 Qualified Names].
82   *
83   * @param v The value to set for the "use-attribute-sets" attribute.
84   */
85  public void setUseAttributeSets(QName[] v)
86  {
87    m_attributeSetsNames = v;
88  }
89
90  /**
91   * Get the "use-attribute-sets" attribute.
92   * Attribute sets are used by specifying a use-attribute-sets
93   * attribute on xsl:element, xsl:copy (see [7.5 Copying]) or
94   * xsl:attribute-set elements, or a xsl:use-attribute-sets attribute on
95   * Literal Result Elements.
96   * The value of the use-attribute-sets
97   * attribute is a whitespace-separated list of names of attribute
98   * sets. Each name is specified as a QName, which is expanded as
99   * 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}
206