blob: b40abcccb072b5d194f64439d53ce1faa0d309a9 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id$
*/
package org.apache.xalan.processor;
import org.apache.xalan.templates.ElemApplyImport;
import org.apache.xalan.templates.ElemApplyTemplates;
import org.apache.xalan.templates.ElemAttribute;
import org.apache.xalan.templates.ElemCallTemplate;
import org.apache.xalan.templates.ElemComment;
import org.apache.xalan.templates.ElemCopy;
import org.apache.xalan.templates.ElemCopyOf;
import org.apache.xalan.templates.ElemElement;
import org.apache.xalan.templates.ElemExsltFuncResult;
import org.apache.xalan.templates.ElemExsltFunction;
import org.apache.xalan.templates.ElemFallback;
import org.apache.xalan.templates.ElemLiteralResult;
import org.apache.xalan.templates.ElemMessage;
import org.apache.xalan.templates.ElemNumber;
import org.apache.xalan.templates.ElemPI;
import org.apache.xalan.templates.ElemParam;
import org.apache.xalan.templates.ElemTemplate;
import org.apache.xalan.templates.ElemTemplateElement;
import org.apache.xalan.templates.ElemText;
import org.apache.xalan.templates.ElemTextLiteral;
import org.apache.xalan.templates.ElemValueOf;
import org.apache.xalan.templates.ElemVariable;
import org.apache.xalan.templates.Stylesheet;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
/**
* This class processes parse events for an exslt func:function element.
* @xsl.usage internal
*/
public class ProcessorExsltFunction extends ProcessorTemplateElem
{
static final long serialVersionUID = 2411427965578315332L;
/**
* Start an ElemExsltFunction. Verify that it is top level and that it has a name attribute with a
* namespace.
*/
public void startElement(
StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes)
throws SAXException
{
//System.out.println("ProcessorFunction.startElement()");
String msg = "";
if (!(handler.getElemTemplateElement() instanceof Stylesheet))
{
msg = "func:function element must be top level.";
handler.error(msg, new SAXException(msg));
}
super.startElement(handler, uri, localName, rawName, attributes);
String val = attributes.getValue("name");
int indexOfColon = val.indexOf(":");
if (indexOfColon > 0)
{
//String prefix = val.substring(0, indexOfColon);
//String localVal = val.substring(indexOfColon + 1);
//String ns = handler.getNamespaceSupport().getURI(prefix);
//if (ns.length() > 0)
// System.out.println("fullfuncname " + ns + localVal);
}
else
{
msg = "func:function name must have namespace";
handler.error(msg, new SAXException(msg));
}
}
/**
* Must include; super doesn't suffice!
*/
protected void appendAndPush(
StylesheetHandler handler, ElemTemplateElement elem)
throws SAXException
{
//System.out.println("ProcessorFunction appendAndPush()" + elem);
super.appendAndPush(handler, elem);
//System.out.println("originating node " + handler.getOriginatingNode());
elem.setDOMBackPointer(handler.getOriginatingNode());
handler.getStylesheet().setTemplate((ElemTemplate) elem);
}
/**
* End an ElemExsltFunction, and verify its validity.
*/
public void endElement(
StylesheetHandler handler, String uri, String localName, String rawName)
throws SAXException
{
ElemTemplateElement function = handler.getElemTemplateElement();
validate(function, handler); // may throw exception
super.endElement(handler, uri, localName, rawName);
}
/**
* Non-recursive traversal of FunctionElement tree based on TreeWalker to verify that
* there are no literal result elements except within a func:result element and that
* the func:result element does not contain any following siblings except xsl:fallback.
*/
public void validate(ElemTemplateElement elem, StylesheetHandler handler)
throws SAXException
{
String msg = "";
while (elem != null)
{
//System.out.println("elem " + elem);
if (elem instanceof ElemExsltFuncResult
&& elem.getNextSiblingElem() != null
&& !(elem.getNextSiblingElem() instanceof ElemFallback))
{
msg = "func:result has an illegal following sibling (only xsl:fallback allowed)";
handler.error(msg, new SAXException(msg));
}
if((elem instanceof ElemApplyImport
|| elem instanceof ElemApplyTemplates
|| elem instanceof ElemAttribute
|| elem instanceof ElemCallTemplate
|| elem instanceof ElemComment
|| elem instanceof ElemCopy
|| elem instanceof ElemCopyOf
|| elem instanceof ElemElement
|| elem instanceof ElemLiteralResult
|| elem instanceof ElemNumber
|| elem instanceof ElemPI
|| elem instanceof ElemText
|| elem instanceof ElemTextLiteral
|| elem instanceof ElemValueOf)
&& !(ancestorIsOk(elem)))
{
msg ="misplaced literal result in a func:function container.";
handler.error(msg, new SAXException(msg));
}
ElemTemplateElement nextElem = elem.getFirstChildElem();
while (nextElem == null)
{
nextElem = elem.getNextSiblingElem();
if (nextElem == null)
elem = elem.getParentElem();
if (elem == null || elem instanceof ElemExsltFunction)
return; // ok
}
elem = nextElem;
}
}
/**
* Verify that a literal result belongs to a result element, a variable,
* or a parameter.
*/
boolean ancestorIsOk(ElemTemplateElement child)
{
while (child.getParentElem() != null && !(child.getParentElem() instanceof ElemExsltFunction))
{
ElemTemplateElement parent = child.getParentElem();
if (parent instanceof ElemExsltFuncResult
|| parent instanceof ElemVariable
|| parent instanceof ElemParam
|| parent instanceof ElemMessage)
return true;
child = parent;
}
return false;
}
}