Home | History | Annotate | Download | only in processor
      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: ProcessorExsltFunction.java 468640 2006-10-28 06:53:53Z minchau $
     20  */
     21 package org.apache.xalan.processor;
     22 
     23 import org.apache.xalan.templates.ElemApplyImport;
     24 import org.apache.xalan.templates.ElemApplyTemplates;
     25 import org.apache.xalan.templates.ElemAttribute;
     26 import org.apache.xalan.templates.ElemCallTemplate;
     27 import org.apache.xalan.templates.ElemComment;
     28 import org.apache.xalan.templates.ElemCopy;
     29 import org.apache.xalan.templates.ElemCopyOf;
     30 import org.apache.xalan.templates.ElemElement;
     31 import org.apache.xalan.templates.ElemExsltFuncResult;
     32 import org.apache.xalan.templates.ElemExsltFunction;
     33 import org.apache.xalan.templates.ElemFallback;
     34 import org.apache.xalan.templates.ElemLiteralResult;
     35 import org.apache.xalan.templates.ElemMessage;
     36 import org.apache.xalan.templates.ElemNumber;
     37 import org.apache.xalan.templates.ElemPI;
     38 import org.apache.xalan.templates.ElemParam;
     39 import org.apache.xalan.templates.ElemTemplate;
     40 import org.apache.xalan.templates.ElemTemplateElement;
     41 import org.apache.xalan.templates.ElemText;
     42 import org.apache.xalan.templates.ElemTextLiteral;
     43 import org.apache.xalan.templates.ElemValueOf;
     44 import org.apache.xalan.templates.ElemVariable;
     45 import org.apache.xalan.templates.Stylesheet;
     46 import org.xml.sax.Attributes;
     47 import org.xml.sax.SAXException;
     48 
     49 
     50 /**
     51  * This class processes parse events for an exslt func:function element.
     52  * @xsl.usage internal
     53  */
     54 public class ProcessorExsltFunction extends ProcessorTemplateElem
     55 {
     56     static final long serialVersionUID = 2411427965578315332L;
     57   /**
     58    * Start an ElemExsltFunction. Verify that it is top level and that it has a name attribute with a
     59    * namespace.
     60    */
     61   public void startElement(
     62           StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes)
     63             throws SAXException
     64   {
     65     //System.out.println("ProcessorFunction.startElement()");
     66     String msg = "";
     67     if (!(handler.getElemTemplateElement() instanceof Stylesheet))
     68     {
     69       msg = "func:function element must be top level.";
     70       handler.error(msg, new SAXException(msg));
     71     }
     72     super.startElement(handler, uri, localName, rawName, attributes);
     73 
     74     String val = attributes.getValue("name");
     75     int indexOfColon = val.indexOf(":");
     76     if (indexOfColon > 0)
     77     {
     78       //String prefix = val.substring(0, indexOfColon);
     79       //String localVal = val.substring(indexOfColon + 1);
     80       //String ns = handler.getNamespaceSupport().getURI(prefix);
     81       //if (ns.length() > 0)
     82       //  System.out.println("fullfuncname " + ns + localVal);
     83     }
     84     else
     85     {
     86       msg = "func:function name must have namespace";
     87       handler.error(msg, new SAXException(msg));
     88     }
     89   }
     90 
     91   /**
     92    * Must include; super doesn't suffice!
     93    */
     94   protected void appendAndPush(
     95           StylesheetHandler handler, ElemTemplateElement elem)
     96             throws SAXException
     97   {
     98     //System.out.println("ProcessorFunction appendAndPush()" + elem);
     99     super.appendAndPush(handler, elem);
    100     //System.out.println("originating node " + handler.getOriginatingNode());
    101     elem.setDOMBackPointer(handler.getOriginatingNode());
    102     handler.getStylesheet().setTemplate((ElemTemplate) elem);
    103   }
    104 
    105   /**
    106    * End an ElemExsltFunction, and verify its validity.
    107    */
    108   public void endElement(
    109           StylesheetHandler handler, String uri, String localName, String rawName)
    110             throws SAXException
    111   {
    112    ElemTemplateElement function = handler.getElemTemplateElement();
    113    validate(function, handler); // may throw exception
    114    super.endElement(handler, uri, localName, rawName);
    115   }
    116 
    117   /**
    118    * Non-recursive traversal of FunctionElement tree based on TreeWalker to verify that
    119    * there are no literal result elements except within a func:result element and that
    120    * the func:result element does not contain any following siblings except xsl:fallback.
    121    */
    122   public void validate(ElemTemplateElement elem, StylesheetHandler handler)
    123     throws SAXException
    124   {
    125     String msg = "";
    126     while (elem != null)
    127     {
    128       //System.out.println("elem " + elem);
    129       if (elem instanceof ElemExsltFuncResult
    130           && elem.getNextSiblingElem() != null
    131           && !(elem.getNextSiblingElem() instanceof ElemFallback))
    132       {
    133         msg = "func:result has an illegal following sibling (only xsl:fallback allowed)";
    134         handler.error(msg, new SAXException(msg));
    135       }
    136 
    137       if((elem instanceof ElemApplyImport
    138 	 || elem instanceof ElemApplyTemplates
    139 	 || elem instanceof ElemAttribute
    140 	 || elem instanceof ElemCallTemplate
    141 	 || elem instanceof ElemComment
    142 	 || elem instanceof ElemCopy
    143 	 || elem instanceof ElemCopyOf
    144 	 || elem instanceof ElemElement
    145 	 || elem instanceof ElemLiteralResult
    146 	 || elem instanceof ElemNumber
    147 	 || elem instanceof ElemPI
    148 	 || elem instanceof ElemText
    149 	 || elem instanceof ElemTextLiteral
    150 	 || elem instanceof ElemValueOf)
    151 	&& !(ancestorIsOk(elem)))
    152       {
    153         msg ="misplaced literal result in a func:function container.";
    154         handler.error(msg, new SAXException(msg));
    155       }
    156       ElemTemplateElement nextElem = elem.getFirstChildElem();
    157       while (nextElem == null)
    158       {
    159         nextElem = elem.getNextSiblingElem();
    160         if (nextElem == null)
    161           elem = elem.getParentElem();
    162         if (elem == null || elem instanceof ElemExsltFunction)
    163           return; // ok
    164       }
    165       elem = nextElem;
    166     }
    167   }
    168 
    169   /**
    170    * Verify that a literal result belongs to a result element, a variable,
    171    * or a parameter.
    172    */
    173 
    174   boolean ancestorIsOk(ElemTemplateElement child)
    175   {
    176     while (child.getParentElem() != null && !(child.getParentElem() instanceof ElemExsltFunction))
    177     {
    178       ElemTemplateElement parent = child.getParentElem();
    179       if (parent instanceof ElemExsltFuncResult
    180           || parent instanceof ElemVariable
    181           || parent instanceof ElemParam
    182           || parent instanceof ElemMessage)
    183         return true;
    184       child = parent;
    185     }
    186     return false;
    187   }
    188 
    189 }
    190