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: ProcessorExsltFunction.java 468640 2006-10-28 06:53:53Z minchau $
020 */
021 package org.apache.xalan.processor;
022
023 import org.apache.xalan.templates.ElemApplyImport;
024 import org.apache.xalan.templates.ElemApplyTemplates;
025 import org.apache.xalan.templates.ElemAttribute;
026 import org.apache.xalan.templates.ElemCallTemplate;
027 import org.apache.xalan.templates.ElemComment;
028 import org.apache.xalan.templates.ElemCopy;
029 import org.apache.xalan.templates.ElemCopyOf;
030 import org.apache.xalan.templates.ElemElement;
031 import org.apache.xalan.templates.ElemExsltFuncResult;
032 import org.apache.xalan.templates.ElemExsltFunction;
033 import org.apache.xalan.templates.ElemFallback;
034 import org.apache.xalan.templates.ElemLiteralResult;
035 import org.apache.xalan.templates.ElemMessage;
036 import org.apache.xalan.templates.ElemNumber;
037 import org.apache.xalan.templates.ElemPI;
038 import org.apache.xalan.templates.ElemParam;
039 import org.apache.xalan.templates.ElemTemplate;
040 import org.apache.xalan.templates.ElemTemplateElement;
041 import org.apache.xalan.templates.ElemText;
042 import org.apache.xalan.templates.ElemTextLiteral;
043 import org.apache.xalan.templates.ElemValueOf;
044 import org.apache.xalan.templates.ElemVariable;
045 import org.apache.xalan.templates.Stylesheet;
046 import org.xml.sax.Attributes;
047 import org.xml.sax.SAXException;
048
049
050 /**
051 * This class processes parse events for an exslt func:function element.
052 * @xsl.usage internal
053 */
054 public class ProcessorExsltFunction extends ProcessorTemplateElem
055 {
056 static final long serialVersionUID = 2411427965578315332L;
057 /**
058 * Start an ElemExsltFunction. Verify that it is top level and that it has a name attribute with a
059 * namespace.
060 */
061 public void startElement(
062 StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes)
063 throws SAXException
064 {
065 //System.out.println("ProcessorFunction.startElement()");
066 String msg = "";
067 if (!(handler.getElemTemplateElement() instanceof Stylesheet))
068 {
069 msg = "func:function element must be top level.";
070 handler.error(msg, new SAXException(msg));
071 }
072 super.startElement(handler, uri, localName, rawName, attributes);
073
074 String val = attributes.getValue("name");
075 int indexOfColon = val.indexOf(":");
076 if (indexOfColon > 0)
077 {
078 //String prefix = val.substring(0, indexOfColon);
079 //String localVal = val.substring(indexOfColon + 1);
080 //String ns = handler.getNamespaceSupport().getURI(prefix);
081 //if (ns.length() > 0)
082 // System.out.println("fullfuncname " + ns + localVal);
083 }
084 else
085 {
086 msg = "func:function name must have namespace";
087 handler.error(msg, new SAXException(msg));
088 }
089 }
090
091 /**
092 * Must include; super doesn't suffice!
093 */
094 protected void appendAndPush(
095 StylesheetHandler handler, ElemTemplateElement elem)
096 throws SAXException
097 {
098 //System.out.println("ProcessorFunction appendAndPush()" + elem);
099 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 }