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    */
startElement( StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes)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    */
appendAndPush( StylesheetHandler handler, ElemTemplateElement elem)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    */
endElement( StylesheetHandler handler, String uri, String localName, String rawName)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    */
validate(ElemTemplateElement elem, StylesheetHandler handler)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 
ancestorIsOk(ElemTemplateElement child)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