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: ElemChoose.java 468643 2006-10-28 06:56:03Z minchau $
020     */
021    package org.apache.xalan.templates;
022    
023    import javax.xml.transform.TransformerException;
024    
025    import org.apache.xalan.res.XSLTErrorResources;
026    import org.apache.xalan.transformer.TransformerImpl;
027    import org.apache.xpath.XPathContext;
028    import org.apache.xpath.objects.XObject;
029    
030    /**
031     * Implement xsl:choose.
032     * <pre>
033     * <!ELEMENT xsl:choose (xsl:when+, xsl:otherwise?)>
034     * <!ATTLIST xsl:choose %space-att;>
035     * </pre>
036     * @see <a href="http://www.w3.org/TR/xslt#section-Conditional-Processing-with-xsl:choose">XXX in XSLT Specification</a>
037     * @xsl.usage advanced
038     */
039    public class ElemChoose extends ElemTemplateElement
040    {
041        static final long serialVersionUID = -3070117361903102033L;
042    
043      /**
044       * Get an int constant identifying the type of element.
045       * @see org.apache.xalan.templates.Constants
046       *
047       * @return The token ID for this element
048       */
049      public int getXSLToken()
050      {
051        return Constants.ELEMNAME_CHOOSE;
052      }
053    
054      /**
055       * Return the node name.
056       *
057       * @return The element's name
058       */
059      public String getNodeName()
060      {
061        return Constants.ELEMNAME_CHOOSE_STRING;
062      }
063    
064      /**
065       * Constructor ElemChoose
066       *
067       */
068      public ElemChoose(){}
069    
070      /**
071       * Execute the xsl:choose transformation.
072       *
073       *
074       * @param transformer non-null reference to the the current transform-time state.
075       *
076       * @throws TransformerException
077       */
078      public void execute(TransformerImpl transformer) throws TransformerException
079      {
080    
081        if (transformer.getDebug())
082          transformer.getTraceManager().fireTraceEvent(this);
083    
084        boolean found = false;
085    
086        for (ElemTemplateElement childElem = getFirstChildElem();
087                childElem != null; childElem = childElem.getNextSiblingElem())
088        {
089          int type = childElem.getXSLToken();
090    
091          if (Constants.ELEMNAME_WHEN == type)
092          {
093            found = true;
094    
095            ElemWhen when = (ElemWhen) childElem;
096    
097            // must be xsl:when
098            XPathContext xctxt = transformer.getXPathContext();
099            int sourceNode = xctxt.getCurrentNode();
100            
101            // System.err.println("\""+when.getTest().getPatternString()+"\"");
102            
103            // if(when.getTest().getPatternString().equals("COLLECTION/icuser/ictimezone/LITERAL='GMT +13:00 Pacific/Tongatapu'"))
104            //      System.err.println("Found COLLECTION/icuser/ictimezone/LITERAL");
105    
106            if (transformer.getDebug())
107            {
108              XObject test = when.getTest().execute(xctxt, sourceNode, when);
109    
110              if (transformer.getDebug())
111                transformer.getTraceManager().fireSelectedEvent(sourceNode, when,
112                        "test", when.getTest(), test);
113    
114              if (test.bool())
115              {
116                transformer.getTraceManager().fireTraceEvent(when);
117                
118                transformer.executeChildTemplates(when, true);
119    
120                    transformer.getTraceManager().fireTraceEndEvent(when); 
121                              
122                return;
123              }
124    
125            }
126            else if (when.getTest().bool(xctxt, sourceNode, when))
127            {
128              transformer.executeChildTemplates(when, true);
129    
130              return;
131            }
132          }
133          else if (Constants.ELEMNAME_OTHERWISE == type)
134          {
135            found = true;
136    
137            if (transformer.getDebug())
138              transformer.getTraceManager().fireTraceEvent(childElem);
139    
140            // xsl:otherwise                
141            transformer.executeChildTemplates(childElem, true);
142    
143            if (transformer.getDebug())
144                  transformer.getTraceManager().fireTraceEndEvent(childElem); 
145            return;
146          }
147        }
148    
149        if (!found)
150          transformer.getMsgMgr().error(
151            this, XSLTErrorResources.ER_CHOOSE_REQUIRES_WHEN);
152            
153        if (transformer.getDebug())
154              transformer.getTraceManager().fireTraceEndEvent(this);         
155      }
156    
157      /**
158       * Add a child to the child list.
159       *
160       * @param newChild Child to add to this node's child list
161       *
162       * @return The child that was just added to the child list
163       *
164       * @throws DOMException
165       */
166      public ElemTemplateElement appendChild(ElemTemplateElement newChild)
167      {
168    
169        int type = ((ElemTemplateElement) newChild).getXSLToken();
170    
171        switch (type)
172        {
173        case Constants.ELEMNAME_WHEN :
174        case Constants.ELEMNAME_OTHERWISE :
175    
176          // TODO: Positional checking
177          break;
178        default :
179          error(XSLTErrorResources.ER_CANNOT_ADD,
180                new Object[]{ newChild.getNodeName(),
181                              this.getNodeName() });  //"Can not add " +((ElemTemplateElement)newChild).m_elemName +
182    
183        //" to " + this.m_elemName);
184        }
185    
186        return super.appendChild(newChild);
187      }
188      
189      /**
190       * Tell if this element can accept variable declarations.
191       * @return true if the element can accept and process variable declarations.
192       */
193      public boolean canAcceptVariables()
194      {
195            return false;
196      }
197    
198    }