001: /*
002: * Copyright 1999-2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: /*
017: * $Id: ProcessorExsltFunction.java,v 1.10 2004/08/17 18:18:08 jycli Exp $
018: */
019: package org.apache.xalan.processor;
020:
021: import javax.xml.transform.SourceLocator;
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.ElemNumber;
036: import org.apache.xalan.templates.ElemPI;
037: import org.apache.xalan.templates.ElemParam;
038: import org.apache.xalan.templates.ElemTemplate;
039: import org.apache.xalan.templates.ElemTemplateElement;
040: import org.apache.xalan.templates.ElemText;
041: import org.apache.xalan.templates.ElemTextLiteral;
042: import org.apache.xalan.templates.ElemValueOf;
043: import org.apache.xalan.templates.ElemVariable;
044: import org.apache.xalan.templates.ElemMessage;
045: import org.apache.xalan.templates.Stylesheet;
046:
047: import org.xml.sax.Attributes;
048: import org.xml.sax.SAXException;
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: static final long serialVersionUID = 2411427965578315332L;
056:
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(StylesheetHandler handler, String uri,
062: String localName, String rawName, Attributes attributes)
063: throws SAXException {
064: //System.out.println("ProcessorFunction.startElement()");
065: String msg = "";
066: if (!(handler.getElemTemplateElement() instanceof Stylesheet)) {
067: msg = "func:function element must be top level.";
068: handler.error(msg, new SAXException(msg));
069: }
070: super
071: .startElement(handler, uri, localName, rawName,
072: attributes);
073:
074: String val = attributes.getValue("name");
075: int indexOfColon = val.indexOf(":");
076: if (indexOfColon > 0) {
077: String prefix = val.substring(0, indexOfColon);
078: String localVal = val.substring(indexOfColon + 1);
079: String ns = handler.getNamespaceSupport().getURI(prefix);
080: //if (ns.length() > 0)
081: // System.out.println("fullfuncname " + ns + localVal);
082: } else {
083: msg = "func:function name must have namespace";
084: handler.error(msg, new SAXException(msg));
085: }
086: }
087:
088: /**
089: * Must include; super doesn't suffice!
090: */
091: protected void appendAndPush(StylesheetHandler handler,
092: ElemTemplateElement elem) throws SAXException {
093: //System.out.println("ProcessorFunction appendAndPush()" + elem);
094: super .appendAndPush(handler, elem);
095: //System.out.println("originating node " + handler.getOriginatingNode());
096: elem.setDOMBackPointer(handler.getOriginatingNode());
097: handler.getStylesheet().setTemplate((ElemTemplate) elem);
098: }
099:
100: /**
101: * End an ElemExsltFunction, and verify its validity.
102: */
103: public void endElement(StylesheetHandler handler, String uri,
104: String localName, String rawName) throws SAXException {
105: ElemTemplateElement function = handler.getElemTemplateElement();
106: SourceLocator locator = handler.getLocator();
107: validate(function, handler); // may throw exception
108: super .endElement(handler, uri, localName, rawName);
109: }
110:
111: /**
112: * Non-recursive traversal of FunctionElement tree based on TreeWalker to verify that
113: * there are no literal result elements except within a func:result element and that
114: * the func:result element does not contain any following siblings except xsl:fallback.
115: */
116: public void validate(ElemTemplateElement elem,
117: StylesheetHandler handler) throws SAXException {
118: String msg = "";
119: while (elem != null) {
120: //System.out.println("elem " + elem);
121: if (elem instanceof ElemExsltFuncResult
122: && elem.getNextSiblingElem() != null
123: && !(elem.getNextSiblingElem() instanceof ElemFallback)) {
124: msg = "func:result has an illegal following sibling (only xsl:fallback allowed)";
125: handler.error(msg, new SAXException(msg));
126: }
127:
128: if ((elem instanceof ElemApplyImport
129: || elem instanceof ElemApplyTemplates
130: || elem instanceof ElemAttribute
131: || elem instanceof ElemCallTemplate
132: || elem instanceof ElemComment
133: || elem instanceof ElemCopy
134: || elem instanceof ElemCopyOf
135: || elem instanceof ElemElement
136: || elem instanceof ElemLiteralResult
137: || elem instanceof ElemNumber
138: || elem instanceof ElemPI
139: || elem instanceof ElemText
140: || elem instanceof ElemTextLiteral || elem instanceof ElemValueOf)
141: && !(ancestorIsOk(elem))) {
142: msg = "misplaced literal result in a func:function container.";
143: handler.error(msg, new SAXException(msg));
144: }
145: ElemTemplateElement nextElem = elem.getFirstChildElem();
146: while (nextElem == null) {
147: nextElem = elem.getNextSiblingElem();
148: if (nextElem == null)
149: elem = elem.getParentElem();
150: if (elem == null || elem instanceof ElemExsltFunction)
151: return; // ok
152: }
153: elem = nextElem;
154: }
155: }
156:
157: /**
158: * Verify that a literal result belongs to a result element, a variable,
159: * or a parameter.
160: */
161:
162: boolean ancestorIsOk(ElemTemplateElement child) {
163: while (child.getParentElem() != null
164: && !(child.getParentElem() instanceof ElemExsltFunction)) {
165: ElemTemplateElement parent = child.getParentElem();
166: if (parent instanceof ElemExsltFuncResult
167: || parent instanceof ElemVariable
168: || parent instanceof ElemParam
169: || parent instanceof ElemMessage)
170: return true;
171: child = parent;
172: }
173: return false;
174: }
175:
176: }
|