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    }