blob: c9af69d3c9ba6d32e5dd7778b365db9a7ed46f86 [file] [log] [blame]
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 1999-2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xalan" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 1999, Lotus
* Development Corporation., http://www.lotus.com. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.xalan.processor;
import org.apache.xml.utils.StringToIntTable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.StringTokenizer;
import java.util.Vector;
import org.apache.xalan.templates.AVT;
import org.apache.xalan.templates.ElemTemplateElement;
import org.apache.xalan.templates.Constants;
import org.apache.xalan.res.XSLMessages;
import org.apache.xalan.res.XSLTErrorResources;
import org.apache.xml.utils.QName;
import org.apache.xml.utils.SystemIDResolver;
import org.apache.xml.utils.StringVector;
import org.apache.xml.utils.XMLChar;
import org.apache.xpath.XPath;
import javax.xml.transform.TransformerException;
/**
* This class defines an attribute for an element in a XSLT stylesheet,
* is meant to reflect the structure defined in http://www.w3.org/TR/xslt#dtd, and the
* mapping between Xalan classes and the markup attributes in the element.
*/
public class XSLTAttributeDef
{
// How to handle invalid values for this attribute
static final int FATAL = 0;
static final int ERROR = 1;
static final int WARNING = 2;
/**
* Construct an instance of XSLTAttributeDef.
*
* @param namespace The Namespace URI, or an empty string.
* @param name The local name (without prefix), or empty string if not namespace processing.
* @param type One of T_CDATA, T_URL, T_AVT, T_PATTERN, T_EXPR, T_CHAR,
* T_NUMBER, T_YESNO, T_QNAME, T_QNAMES, T_ENUM, T_SIMPLEPATTERNLIST,
* T_NMTOKEN, T_STRINGLIST, T_PREFIX_URLLIST, T_ENUM_OR_PQNAME, T_NCNAME.
* @param required true if this is attribute is required by the XSLT specification.
* @param supportsAVT true if this attribute supports AVT's.
* @param errorType the type of error to issue if validation fails. One of FATAL, ERROR, WARNING.
*/
XSLTAttributeDef(String namespace, String name, int type, boolean required, boolean supportsAVT, int errorType)
{
this.m_namespace = namespace;
this.m_name = name;
this.m_type = type;
this.m_required = required;
this.m_supportsAVT = supportsAVT;
this.m_errorType = errorType;
}
/**
* Construct an instance of XSLTAttributeDef.
*
* @param namespace The Namespace URI, or an empty string.
* @param name The local name (without prefix), or empty string if not namespace processing.
* @param type One of T_CDATA, T_URL, T_AVT, T_PATTERN, T_EXPR,
* T_CHAR, T_NUMBER, T_YESNO, T_QNAME, T_QNAMES, T_ENUM,
* T_SIMPLEPATTERNLIST, T_NMTOKEN, T_STRINGLIST, T_PREFIX_URLLIST,
* T_ENUM_OR_PQNAME, T_NCNAME.
* @param supportsAVT true if this attribute supports AVT's.
* @param errorType the type of error to issue if validation fails. One of FATAL, ERROR, WARNING.
* @param defaultVal The default value for this attribute.
*/
XSLTAttributeDef(String namespace, String name, int type, boolean supportsAVT, int errorType, String defaultVal)
{
this.m_namespace = namespace;
this.m_name = name;
this.m_type = type;
this.m_required = false;
this.m_supportsAVT = supportsAVT;
this.m_errorType = errorType;
this.m_default = defaultVal;
}
/**
* Construct an instance of XSLTAttributeDef that uses two
* enumerated values.
*
* @param namespace The Namespace URI, or an empty string.
* @param name The local name (without prefix), or empty string if not namespace processing.
* @param required true if this attribute is required by the XSLT specification.
* @param supportsAVT true if this attribute supports AVT's.
* @param prefixedQNameValAllowed If true, the type is T_ENUM_OR_PQNAME
* @param errorType the type of error to issue if validation fails. One of FATAL, ERROR, WARNING.
* @param k1 The XSLT name of the enumerated value.
* @param v1 An integer representation of k1.
* @param k2 The XSLT name of the enumerated value.
* @param v2 An integer representation of k2.
*/
XSLTAttributeDef(String namespace, String name, boolean required, boolean supportsAVT,
boolean prefixedQNameValAllowed, int errorType, String k1, int v1, String k2, int v2)
{
this.m_namespace = namespace;
this.m_name = name;
this.m_type = prefixedQNameValAllowed ? this.T_ENUM_OR_PQNAME : this.T_ENUM;
this.m_required = required;
this.m_supportsAVT = supportsAVT;
this.m_errorType = errorType;
m_enums = new StringToIntTable(2);
m_enums.put(k1, v1);
m_enums.put(k2, v2);
}
/**
* Construct an instance of XSLTAttributeDef that uses three
* enumerated values.
*
* @param namespace The Namespace URI, or an empty string.
* @param name The local name (without prefix), or empty string if not namespace processing.
* @param required true if this attribute is required by the XSLT specification.
* @param supportsAVT true if this attribute supports AVT's.
* @param prefixedQNameValAllowed If true, the type is T_ENUM_OR_PQNAME
* @param errorType the type of error to issue if validation fails. One of FATAL, ERROR, WARNING. *
* @param k1 The XSLT name of the enumerated value.
* @param v1 An integer representation of k1.
* @param k2 The XSLT name of the enumerated value.
* @param v2 An integer representation of k2.
* @param k3 The XSLT name of the enumerated value.
* @param v3 An integer representation of k3.
*/
XSLTAttributeDef(String namespace, String name, boolean required, boolean supportsAVT,
boolean prefixedQNameValAllowed, int errorType, String k1, int v1, String k2, int v2, String k3, int v3)
{
this.m_namespace = namespace;
this.m_name = name;
this.m_type = prefixedQNameValAllowed ? this.T_ENUM_OR_PQNAME : this.T_ENUM;
this.m_required = required;
this.m_supportsAVT = supportsAVT;
this.m_errorType = errorType;
m_enums = new StringToIntTable(3);
m_enums.put(k1, v1);
m_enums.put(k2, v2);
m_enums.put(k3, v3);
}
/**
* Construct an instance of XSLTAttributeDef that uses three
* enumerated values.
*
* @param namespace The Namespace URI, or an empty string.
* @param name The local name (without prefix), or empty string if not namespace processing.
* @param required true if this attribute is required by the XSLT specification.
* @param supportsAVT true if this attribute supports AVT's.
* @param prefixedQNameValAllowed If true, the type is T_ENUM_OR_PQNAME
* @param errorType the type of error to issue if validation fails. One of FATAL, ERROR, WARNING. * @param k1 The XSLT name of the enumerated value.
* @param v1 An integer representation of k1.
* @param k2 The XSLT name of the enumerated value.
* @param v2 An integer representation of k2.
* @param k3 The XSLT name of the enumerated value.
* @param v3 An integer representation of k3.
* @param k4 The XSLT name of the enumerated value.
* @param v4 An integer representation of k4.
*/
XSLTAttributeDef(String namespace, String name, boolean required, boolean supportsAVT,
boolean prefixedQNameValAllowed, int errorType, String k1, int v1, String k2, int v2,
String k3, int v3, String k4, int v4)
{
this.m_namespace = namespace;
this.m_name = name;
this.m_type = prefixedQNameValAllowed ? this.T_ENUM_OR_PQNAME : this.T_ENUM;
this.m_required = required;
this.m_supportsAVT = supportsAVT;
this.m_errorType = errorType;
m_enums = new StringToIntTable(4);
m_enums.put(k1, v1);
m_enums.put(k2, v2);
m_enums.put(k3, v3);
m_enums.put(k4, v4);
}
/** Type values that represent XSLT attribute types. */
static final int T_CDATA = 1,
// <!-- Used for the type of an attribute value that is a URI reference.-->
T_URL = 2,
// <!-- Used for the type of an attribute value that is an
// attribute value template.-->
T_AVT = 3, // Attribute Value Template
// <!-- Used for the type of an attribute value that is a pattern.-->
T_PATTERN = 4,
// <!-- Used for the type of an attribute value that is an expression.-->
T_EXPR = 5,
// <!-- Used for the type of an attribute value that consists
// of a single character.-->
T_CHAR = 6,
// <!-- Used for the type of an attribute value that is a number. -->
T_NUMBER = 7,
// Used for boolean values
T_YESNO = 8,
// <!-- Used for the type of an attribute value that is a QName; the prefix
// gets expanded by the XSLT processor. -->
T_QNAME = 9,
// <!--Used for a whitespace-separated list of QNames where the non-prefixed
// entries are not to be placed in the default namespace. -->
T_QNAMES = 10,
// <!-- Used for enumerated values -->
T_ENUM = 11,
// Used for simple match patterns, i.e. xsl:strip-space spec.
T_SIMPLEPATTERNLIST = 12,
// Used for a known token.
T_NMTOKEN = 13,
// Used for a list of white-space delimited strings.
T_STRINGLIST = 14,
// Used for a list of white-space delimited strings.
T_PREFIX_URLLIST = 15,
// Used for enumerated values, one of which could be a qname-but-not-ncname
T_ENUM_OR_PQNAME = 16,
// Used for the type of an attribute value that is a NCName
T_NCNAME = 17,
// Used for QName attributes that are always AVT. Prefix isn't resolved.
T_AVT_QNAME = 18,
// Used for a list of QNames where non-prefixed items are to be resolved
// using the default namespace (This is only true for cdata-section-elements)
T_QNAMES_RESOLVE_NULL = 19;
/** Representation for an attribute in a foreign namespace. */
static XSLTAttributeDef m_foreignAttr = new XSLTAttributeDef("*", "*",
XSLTAttributeDef.T_CDATA,false, false, WARNING);
/** Method name that objects may implement if they wish to have forein attributes set. */
static String S_FOREIGNATTR_SETTER = "setForeignAttr";
/**
* The allowed namespace for this element.
*/
private String m_namespace;
/**
* Get the allowed namespace for this attribute.
*
* @return The allowed namespace for this attribute, which may be null, or may be "*".
*/
String getNamespace()
{
return m_namespace;
}
/**
* The name of this element.
*/
private String m_name;
/**
* Get the name of this attribute.
*
* @return non-null reference to the name of this attribute, which may be "*".
*/
String getName()
{
return m_name;
}
/**
* The type of this attribute value.
*/
private int m_type;
/**
* Get the type of this attribute value.
*
* @return One of T_CDATA, T_URL, T_AVT, T_PATTERN, T_EXPR, T_CHAR,
* T_NUMBER, T_YESNO, T_QNAME, T_QNAMES, T_ENUM, T_SIMPLEPATTERNLIST,
* T_NMTOKEN, T_STRINGLIST, T_PREFIX_URLLIST, T_ENUM_OR_PQNAME.
*/
int getType()
{
return m_type;
}
/**
* If this element is of type T_ENUM, this will contain
* a map from the attribute string to the Xalan integer
* value.
*/
private StringToIntTable m_enums;
/**
* If this element is of type T_ENUM, this will return
* a map from the attribute string to the Xalan integer
* value.
* @param key The XSLT attribute value.
*
* @return The integer representation of the enumerated value for this attribute.
* @throws Throws NullPointerException if m_enums is null.
*/
private int getEnum(String key)
{
return m_enums.get(key);
}
/**
* If this element is of type T_ENUM, this will return
* an array of strings - the values in the enumeration
*
* @return An array of the enumerated values permitted for this attribute.
*
* @throws Throws NullPointerException if m_enums is null.
*/
private String[] getEnumNames()
{
return m_enums.keys();
}
/**
* The default value for this attribute.
*/
private String m_default;
/**
* Get the default value for this attribute.
*
* @return The default value for this attribute, or null.
*/
String getDefault()
{
return m_default;
}
/**
* Set the default value for this attribute.
*
* @param def String representation of the default value for this attribute.
*/
void setDefault(String def)
{
m_default = def;
}
/**
* If true, this is a required attribute.
*/
private boolean m_required;
/**
* Get whether or not this is a required attribute.
*
* @return true if this is a required attribute.
*/
boolean getRequired()
{
return m_required;
}
/**
* If true, this is attribute supports AVT's.
*/
private boolean m_supportsAVT;
/**
* Get whether or not this attribute supports AVT's.
*
* @return true if this attribute supports AVT's.
*/
boolean getSupportsAVT()
{
return m_supportsAVT;
}
int m_errorType = this.WARNING;
/**
* Get the type of error message to use if the attribute value is invalid.
*
* @return one of XSLAttributeDef.FATAL, XSLAttributeDef.ERROR, XSLAttributeDef.WARNING
*/
int getErrorType()
{
return m_errorType;
}
/**
* String that should represent the setter method which which
* may be used on objects to set a value that represents this attribute
*/
String m_setterString = null;
/**
* Return a string that should represent the setter method.
* The setter method name will be created algorithmically the
* first time this method is accessed, and then cached for return
* by subsequent invocations of this method.
*
* @return String that should represent the setter method which which
* may be used on objects to set a value that represents this attribute,
* of null if no setter method should be called.
*/
public String getSetterMethodName()
{
if (null == m_setterString)
{
if (m_foreignAttr == this)
{
return S_FOREIGNATTR_SETTER;
}
else if (m_name.equals("*"))
{
m_setterString = "addLiteralResultAttribute";
return m_setterString;
}
StringBuffer outBuf = new StringBuffer();
outBuf.append("set");
if ((m_namespace != null)
&& m_namespace.equals(Constants.S_XMLNAMESPACEURI))
{
outBuf.append("Xml");
}
int n = m_name.length();
for (int i = 0; i < n; i++)
{
char c = m_name.charAt(i);
if ('-' == c)
{
i++;
c = m_name.charAt(i);
c = Character.toUpperCase(c);
}
else if (0 == i)
{
c = Character.toUpperCase(c);
}
outBuf.append(c);
}
m_setterString = outBuf.toString();
}
return m_setterString;
}
/**
* Process an attribute string of type T_AVT into
* a AVT value.
*
* @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
* @param uri The Namespace URI, or an empty string.
* @param name The local name (without prefix), or empty string if not namespace processing.
* @param rawName The qualified name (with prefix).
* @param value Should be an Attribute Value Template string.
*
* @return An AVT object that may be used to evaluate the Attribute Value Template.
*
* @throws org.xml.sax.SAXException which will wrap a
* {@link javax.xml.transform.TransformerException}, if there is a syntax error
* in the attribute value template string.
*/
AVT processAVT(
StylesheetHandler handler, String uri, String name, String rawName, String value,
ElemTemplateElement owner)
throws org.xml.sax.SAXException
{
try
{
AVT avt = new AVT(handler, uri, name, rawName, value, owner);
return avt;
}
catch (TransformerException te)
{
throw new org.xml.sax.SAXException(te);
}
}
/**
* Process an attribute string of type T_CDATA into
* a String value.
*
* @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
* @param uri The Namespace URI, or an empty string.
* @param name The local name (without prefix), or empty string if not namespace processing.
* @param rawName The qualified name (with prefix).
* @param value non-null string reference.
*
* @return The value argument.
*
* @throws org.xml.sax.SAXException.
*/
Object processCDATA(StylesheetHandler handler, String uri, String name,
String rawName, String value, ElemTemplateElement owner)
throws org.xml.sax.SAXException
{
if (getSupportsAVT()) {
try
{
AVT avt = new AVT(handler, uri, name, rawName, value, owner);
return avt;
}
catch (TransformerException te)
{
throw new org.xml.sax.SAXException(te);
}
} else {
return value;
}
}
/**
* Process an attribute string of type T_CHAR into
* a Character value.
*
* @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
* @param uri The Namespace URI, or an empty string.
* @param name The local name (without prefix), or empty string if not namespace processing.
* @param rawName The qualified name (with prefix).
* @param value Should be a string with a length of 1.
*
* @return Character object.
*
* @throws org.xml.sax.SAXException if the string is not a length of 1.
*/
Object processCHAR(
StylesheetHandler handler, String uri, String name, String rawName, String value, ElemTemplateElement owner)
throws org.xml.sax.SAXException
{
if (getSupportsAVT()) {
try
{
AVT avt = new AVT(handler, uri, name, rawName, value, owner);
// If an AVT wasn't used, validate the value
if ((avt.isSimple()) && (value.length() != 1)) {
handleError(handler, XSLTErrorResources.INVALID_TCHAR, new Object[] {name, value},null);
return null;
}
return avt;
}
catch (TransformerException te)
{
throw new org.xml.sax.SAXException(te);
}
} else {
if (value.length() != 1)
{
handleError(handler, XSLTErrorResources.INVALID_TCHAR, new Object[] {name, value},null);
return null;
}
return new Character(value.charAt(0));
}
}
/**
* Process an attribute string of type T_ENUM into a int value.
*
* @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
* @param uri The Namespace URI, or an empty string.
* @param name The local name (without prefix), or empty string if not namespace processing.
* @param rawName The qualified name (with prefix).
* @param value non-null string that represents an enumerated value that is
* valid for this element.
* @param owner
*
* @return An Integer representation of the enumerated value if this attribute does not support
* AVT. Otherwise, and AVT is returned.
*/
Object processENUM(StylesheetHandler handler, String uri, String name,
String rawName, String value, ElemTemplateElement owner)
throws org.xml.sax.SAXException
{
AVT avt = null;
if (getSupportsAVT()) {
try
{
avt = new AVT(handler, uri, name, rawName, value, owner);
// If this attribute used an avt, then we can't validate at this time.
if (!avt.isSimple()) return avt;
}
catch (TransformerException te)
{
throw new org.xml.sax.SAXException(te);
}
}
int retVal = this.getEnum(value);
if (retVal == StringToIntTable.INVALID_KEY)
{
StringBuffer enumNamesList = getListOfEnums();
handleError(handler, XSLTErrorResources.INVALID_ENUM,new Object[]{name, value, enumNamesList.toString() },null);
return null;
}
if (getSupportsAVT()) return avt;
else return new Integer(retVal);
}
/**
* Process an attribute string of that is either an enumerated value or a qname-but-not-ncname.
* Returns an AVT, if this attribute support AVT; otherwise returns int or qname.
*
* @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
* @param uri The Namespace URI, or an empty string.
* @param name The local name (without prefix), or empty string if not namespace processing.
* @param rawName The qualified name (with prefix).
* @param value non-null string that represents an enumerated value that is
* valid for this element.
* @param owner
*
* @return AVT if attribute supports AVT. An Integer representation of the enumerated value if
* attribute does not support AVT and an enumerated value was used. Otherwise a qname
* is returned.
*/
Object processENUM_OR_PQNAME(StylesheetHandler handler, String uri, String name,
String rawName, String value, ElemTemplateElement owner)
throws org.xml.sax.SAXException
{
Object objToReturn = null;
if (getSupportsAVT()) {
try
{
AVT avt = new AVT(handler, uri, name, rawName, value, owner);
if (!avt.isSimple()) return avt;
else objToReturn = avt;
}
catch (TransformerException te)
{
throw new org.xml.sax.SAXException(te);
}
}
// An avt wasn't used.
int enum = this.getEnum(value);
if (enum != StringToIntTable.INVALID_KEY)
{
if (objToReturn == null) objToReturn = new Integer(enum);
}
// enum not used. Validate qname-but-not-ncname.
else
{
try
{
QName qname = new QName(value, handler, true);
if (objToReturn == null) objToReturn = qname;
if (qname.getPrefix() == null) {
StringBuffer enumNamesList = getListOfEnums();
enumNamesList.append(" <qname-but-not-ncname>");
handleError(handler,XSLTErrorResources.INVALID_ENUM,new Object[]{name, value, enumNamesList.toString() },null);
return null;
}
}
catch (IllegalArgumentException ie)
{
StringBuffer enumNamesList = getListOfEnums();
enumNamesList.append(" <qname-but-not-ncname>");
handleError(handler,XSLTErrorResources.INVALID_ENUM,new Object[]{name, value, enumNamesList.toString() },ie);
return null;
}
catch (RuntimeException re)
{
StringBuffer enumNamesList = getListOfEnums();
enumNamesList.append(" <qname-but-not-ncname>");
handleError(handler,XSLTErrorResources.INVALID_ENUM,new Object[]{name, value, enumNamesList.toString() },re);
return null;
}
}
return objToReturn;
}
/**
* Process an attribute string of type T_EXPR into
* an XPath value.
*
* @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
* @param uri The Namespace URI, or an empty string.
* @param name The local name (without prefix), or empty string if not namespace processing.
* @param rawName The qualified name (with prefix).
* @param value An XSLT expression string.
*
* @return an XPath object that may be used for evaluation.
*
* @throws org.xml.sax.SAXException that wraps a
* {@link javax.xml.transform.TransformerException} if the expression
* string contains a syntax error.
*/
Object processEXPR(
StylesheetHandler handler, String uri, String name, String rawName, String value,
ElemTemplateElement owner)
throws org.xml.sax.SAXException
{
try
{
XPath expr = handler.createXPath(value, owner);
return expr;
}
catch (TransformerException te)
{
org.xml.sax.SAXException se = new org.xml.sax.SAXException(te);
throw new org.xml.sax.SAXException(te);
}
}
/**
* Process an attribute string of type T_NMTOKEN into
* a String value.
*
* @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
* @param uri The Namespace URI, or an empty string.
* @param name The local name (without prefix), or empty string if not namespace processing.
* @param rawName The qualified name (with prefix).
* @param value A NMTOKEN string.
*
* @return the value argument or an AVT if this attribute supports AVTs.
*
* @throws org.xml.sax.SAXException if the value is not a valid nmtoken
*/
Object processNMTOKEN(StylesheetHandler handler, String uri, String name,
String rawName, String value, ElemTemplateElement owner)
throws org.xml.sax.SAXException
{
if (getSupportsAVT()) {
try
{
AVT avt = new AVT(handler, uri, name, rawName, value, owner);
// If an AVT wasn't used, validate the value
if ((avt.isSimple()) && (!XMLChar.isValidNmtoken(value))) {
handleError(handler,XSLTErrorResources.INVALID_NMTOKEN, new Object[] {name,value},null);
return null;
}
return avt;
}
catch (TransformerException te)
{
throw new org.xml.sax.SAXException(te);
}
} else {
if (!XMLChar.isValidNmtoken(value)) {
handleError(handler,XSLTErrorResources.INVALID_NMTOKEN, new Object[] {name,value},null);
return null;
}
}
return value;
}
/**
* Process an attribute string of type T_PATTERN into
* an XPath match pattern value.
*
* @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
* @param uri The Namespace URI, or an empty string.
* @param name The local name (without prefix), or empty string if not namespace processing.
* @param rawName The qualified name (with prefix).
* @param value A match pattern string.
*
* @return An XPath pattern that may be used to evaluate the XPath.
*
* @throws org.xml.sax.SAXException that wraps a
* {@link javax.xml.transform.TransformerException} if the match pattern
* string contains a syntax error.
*/
Object processPATTERN(
StylesheetHandler handler, String uri, String name, String rawName, String value,
ElemTemplateElement owner)
throws org.xml.sax.SAXException
{
try
{
XPath pattern = handler.createMatchPatternXPath(value, owner);
return pattern;
}
catch (TransformerException te)
{
throw new org.xml.sax.SAXException(te);
}
}
/**
* Process an attribute string of type T_NUMBER into
* a double value.
*
* @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
* @param uri The Namespace URI, or an empty string.
* @param name The local name (without prefix), or empty string if not namespace processing.
* @param rawName The qualified name (with prefix).
* @param value A string that can be parsed into a double value.
* @param number
*
* @return A Double object.
*
* @throws org.xml.sax.SAXException that wraps a
* {@link javax.xml.transform.TransformerException}
* if the string does not contain a parsable number.
*/
Object processNUMBER(
StylesheetHandler handler, String uri, String name, String rawName, String value, ElemTemplateElement owner)
throws org.xml.sax.SAXException
{
if (getSupportsAVT())
{
Double val;
AVT avt = null;
try
{
avt = new AVT(handler, uri, name, rawName, value, owner);
// If this attribute used an avt, then we can't validate at this time.
if (avt.isSimple())
{
val = Double.valueOf(value);
}
}
catch (TransformerException te)
{
throw new org.xml.sax.SAXException(te);
}
catch (NumberFormatException nfe)
{
handleError(handler,XSLTErrorResources.INVALID_NUMBER, new Object[] {name, value}, nfe);
return null;
}
return avt;
}
else
{
try
{
return Double.valueOf(value);
}
catch (NumberFormatException nfe)
{
handleError(handler,XSLTErrorResources.INVALID_NUMBER, new Object[] {name, value}, nfe);
return null;
}
}
}
/**
* Process an attribute string of type T_QNAME into a QName value.
*
* @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
* @param uri The Namespace URI, or an empty string.
* @param name The local name (without prefix), or empty string if not namespace processing.
* @param rawName The qualified name (with prefix).
* @param value A string that represents a potentially prefix qualified name.
* @param owner
*
* @return A QName object if this attribute does not support AVT's. Otherwise, an AVT
* is returned.
*
* @throws org.xml.sax.SAXException if the string contains a prefix that can not be
* resolved, or the string contains syntax that is invalid for a qualified name.
*/
Object processQNAME(
StylesheetHandler handler, String uri, String name, String rawName, String value, ElemTemplateElement owner)
throws org.xml.sax.SAXException
{
try
{
QName qname = new QName(value, handler, true);
return qname;
}
catch (IllegalArgumentException ie)
{
// thrown by QName constructor
handleError(handler,XSLTErrorResources.INVALID_QNAME, new Object[] {name, value},ie);
return null;
}
catch (RuntimeException re) {
// thrown by QName constructor
handleError(handler,XSLTErrorResources.INVALID_QNAME, new Object[] {name, value},re);
return null;
}
}
/**
* Process an attribute string of type T_QNAME into a QName value.
*
* @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
* @param uri The Namespace URI, or an empty string.
* @param name The local name (without prefix), or empty string if not namespace processing.
* @param rawName The qualified name (with prefix).
* @param value A string that represents a potentially prefix qualified name.
* @param owner
*
* @return An AVT is returned.
*
* @throws org.xml.sax.SAXException if the string contains a prefix that can not be
* resolved, or the string contains syntax that is invalid for a qualified name.
*/
Object processAVT_QNAME(
StylesheetHandler handler, String uri, String name, String rawName, String value, ElemTemplateElement owner)
throws org.xml.sax.SAXException
{
AVT avt = null;
try
{
avt = new AVT(handler, uri, name, rawName, value, owner);
// If an AVT wasn't used, validate the value
if (avt.isSimple())
{
int indexOfNSSep = value.indexOf(':');
if (indexOfNSSep >= 0)
{
String prefix = value.substring(0, indexOfNSSep);
if (!XMLChar.isValidNCName(prefix))
{
handleError(handler,XSLTErrorResources.INVALID_QNAME,new Object[]{name,value },null);
return null;
}
}
String localName = (indexOfNSSep < 0)
? value : value.substring(indexOfNSSep + 1);
if ((localName == null) || (localName.length() == 0) ||
(!XMLChar.isValidNCName(localName)))
{
handleError(handler,XSLTErrorResources.INVALID_QNAME,new Object[]{name,value },null );
return null;
}
}
}
catch (TransformerException te)
{
// thrown by AVT constructor
throw new org.xml.sax.SAXException(te);
}
return avt;
}
/**
* Process an attribute string of type NCName into a String
*
* @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
* @param uri The Namespace URI, or an empty string.
* @param name The local name (without prefix), or empty string if not namespace processing.
* @param rawName The qualified name (with prefix).
* @param value A string that represents a potentially prefix qualified name.
* @param owner
*
* @return A String object if this attribute does not support AVT's. Otherwise, an AVT
* is returned.
*
* @throws org.xml.sax.SAXException if the string contains a prefix that can not be
* resolved, or the string contains syntax that is invalid for a NCName.
*/
Object processNCNAME(
StylesheetHandler handler, String uri, String name, String rawName, String value, ElemTemplateElement owner)
throws org.xml.sax.SAXException
{
if (getSupportsAVT())
{
AVT avt = null;
try
{
avt = new AVT(handler, uri, name, rawName, value, owner);
// If an AVT wasn't used, validate the value
if ((avt.isSimple()) && (!XMLChar.isValidNCName(value)))
{
handleError(handler,XSLTErrorResources.INVALID_NCNAME,new Object[] {name,value},null);
return null;
}
return avt;
}
catch (TransformerException te)
{
// thrown by AVT constructor
throw new org.xml.sax.SAXException(te);
}
} else {
if (!XMLChar.isValidNCName(value))
{
handleError(handler,XSLTErrorResources.INVALID_NCNAME,new Object[] {name,value},null);
return null;
}
return value;
}
}
/**
* Process an attribute string of type T_QNAMES into a vector of QNames where
* the specification requires that non-prefixed elements not be placed in a
* namespace. (See section 2.4 of XSLT 1.0.)
*
* @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
* @param uri The Namespace URI, or an empty string.
* @param name The local name (without prefix), or empty string if not namespace processing.
* @param rawName The qualified name (with prefix).
* @param value A whitespace delimited list of qualified names.
*
* @return a Vector of QName objects.
*
* @throws org.xml.sax.SAXException if the one of the qualified name strings
* contains a prefix that can not be
* resolved, or a qualified name contains syntax that is invalid for a qualified name.
*/
Vector processQNAMES(
StylesheetHandler handler, String uri, String name, String rawName, String value)
throws org.xml.sax.SAXException
{
StringTokenizer tokenizer = new StringTokenizer(value, " \t\n\r\f");
int nQNames = tokenizer.countTokens();
Vector qnames = new Vector(nQNames);
for (int i = 0; i < nQNames; i++)
{
// Fix from Alexander Rudnev
qnames.addElement(new QName(tokenizer.nextToken(), handler));
}
return qnames;
}
/**
* Process an attribute string of type T_QNAMES_RESOLVE_NULL into a vector
* of QNames where the specification requires non-prefixed elements to be
* placed in the default namespace. (See section 16 of XSLT 1.0; the
* <em>only</em> time that this will get called is for the
* <code>cdata-section-elements</code> attribute on <code>xsl:output</code>.
*
* @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
* @param uri The Namespace URI, or an empty string.
* @param name The local name (without prefix), or empty string if not namespace processing.
* @param rawName The qualified name (with prefix).
* @param value A whitespace delimited list of qualified names.
*
* @return a Vector of QName objects.
*
* @throws org.xml.sax.SAXException if the one of the qualified name strings
* contains a prefix that can not be resolved, or a qualified name contains
* syntax that is invalid for a qualified name.
*/
final Vector processQNAMESRNU(StylesheetHandler handler, String uri,
String name, String rawName, String value)
throws org.xml.sax.SAXException
{
StringTokenizer tokenizer = new StringTokenizer(value, " \t\n\r\f");
int nQNames = tokenizer.countTokens();
Vector qnames = new Vector(nQNames);
String defaultURI = handler.getNamespaceForPrefix("");
for (int i = 0; i < nQNames; i++)
{
String tok = tokenizer.nextToken();
if (tok.indexOf(':') == -1) {
qnames.addElement(new QName(defaultURI,tok));
} else {
qnames.addElement(new QName(tok, handler));
}
}
return qnames;
}
/**
* Process an attribute string of type T_SIMPLEPATTERNLIST into
* a vector of XPath match patterns.
*
* @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
* @param uri The Namespace URI, or an empty string.
* @param name The local name (without prefix), or empty string if not namespace processing.
* @param rawName The qualified name (with prefix).
* @param value A whitespace delimited list of simple match patterns.
*
* @return A Vector of XPath objects.
*
* @throws org.xml.sax.SAXException that wraps a
* {@link javax.xml.transform.TransformerException} if one of the match pattern
* strings contains a syntax error.
*/
Vector processSIMPLEPATTERNLIST(
StylesheetHandler handler, String uri, String name, String rawName, String value,
ElemTemplateElement owner)
throws org.xml.sax.SAXException
{
try
{
StringTokenizer tokenizer = new StringTokenizer(value, " \t\n\r\f");
int nPatterns = tokenizer.countTokens();
Vector patterns = new Vector(nPatterns);
for (int i = 0; i < nPatterns; i++)
{
XPath pattern =
handler.createMatchPatternXPath(tokenizer.nextToken(), owner);
patterns.addElement(pattern);
}
return patterns;
}
catch (TransformerException te)
{
throw new org.xml.sax.SAXException(te);
}
}
/**
* Process an attribute string of type T_STRINGLIST into
* a vector of XPath match patterns.
*
* @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
* @param uri The Namespace URI, or an empty string.
* @param name The local name (without prefix), or empty string if not namespace processing.
* @param rawName The qualified name (with prefix).
* @param value a whitespace delimited list of string values.
*
* @return A StringVector of the tokenized strings.
*/
StringVector processSTRINGLIST(StylesheetHandler handler, String uri,
String name, String rawName, String value)
{
StringTokenizer tokenizer = new StringTokenizer(value, " \t\n\r\f");
int nStrings = tokenizer.countTokens();
StringVector strings = new StringVector(nStrings);
for (int i = 0; i < nStrings; i++)
{
strings.addElement(tokenizer.nextToken());
}
return strings;
}
/**
* Process an attribute string of type T_URLLIST into
* a vector of prefixes that may be resolved to URLs.
*
* @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
* @param uri The Namespace URI, or an empty string.
* @param name The local name (without prefix), or empty string if not namespace processing.
* @param rawName The qualified name (with prefix).
* @param value A list of whitespace delimited prefixes.
*
* @return A vector of strings that may be resolved to URLs.
*
* @throws org.xml.sax.SAXException if one of the prefixes can not be resolved.
*/
StringVector processPREFIX_URLLIST(
StylesheetHandler handler, String uri, String name, String rawName, String value)
throws org.xml.sax.SAXException
{
StringTokenizer tokenizer = new StringTokenizer(value, " \t\n\r\f");
int nStrings = tokenizer.countTokens();
StringVector strings = new StringVector(nStrings);
for (int i = 0; i < nStrings; i++)
{
String prefix = tokenizer.nextToken();
String url = handler.getNamespaceForPrefix(prefix);
if (url != null)
strings.addElement(url);
else
throw new org.xml.sax.SAXException(XSLMessages.createMessage(XSLTErrorResources.ER_CANT_RESOLVE_NSPREFIX, new Object[] {prefix}));
}
return strings;
}
/**
* Process an attribute string of type T_URL into
* a URL value.
*
* @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
* @param uri The Namespace URI, or an empty string.
* @param name The local name (without prefix), or empty string if not namespace processing.
* @param rawName The qualified name (with prefix).
* @param value non-null string that conforms to the URL syntax.
*
* @return The non-absolutized URL argument, in other words, the value argument. If this
* attribute supports AVT, an AVT is returned.
*
* @throws org.xml.sax.SAXException if the URL does not conform to the URL syntax.
*/
Object processURL(
StylesheetHandler handler, String uri, String name, String rawName, String value, ElemTemplateElement owner)
throws org.xml.sax.SAXException
{
if (getSupportsAVT()) {
try
{
AVT avt = new AVT(handler, uri, name, rawName, value, owner);
// If an AVT wasn't used, validate the value
// if (avt.getSimpleString() != null) {
// TODO: syntax check URL value.
// return SystemIDResolver.getAbsoluteURI(value,
// handler.getBaseIdentifier());
//}
return avt;
}
catch (TransformerException te)
{
throw new org.xml.sax.SAXException(te);
}
} else {
// TODO: syntax check URL value.
// return SystemIDResolver.getAbsoluteURI(value,
// handler.getBaseIdentifier());
return value;
}
}
/**
* Process an attribute string of type T_YESNO into
* a Boolean value.
*
* @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
* @param uri The Namespace URI, or an empty string.
* @param name The local name (without prefix), or empty string if not namespace processing.
* @param rawName The qualified name (with prefix).
* @param value A string that should be "yes" or "no".
*
* @return Boolean object representation of the value.
*
* @throws org.xml.sax.SAXException
*/
private Boolean processYESNO(
StylesheetHandler handler, String uri, String name, String rawName, String value)
throws org.xml.sax.SAXException
{
// Is this already checked somewhere else? -sb
if (!(value.equals("yes") || value.equals("no")))
{
handleError(handler, XSLTErrorResources.INVALID_BOOLEAN, new Object[] {name,value}, null);
return null;
}
return new Boolean(value.equals("yes") ? true : false);
}
/**
* Process an attribute value.
*
* @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
* @param uri The Namespace URI, or an empty string.
* @param name The local name (without prefix), or empty string if not namespace processing.
* @param rawName The qualified name (with prefix).
* @param value The unprocessed string value of the attribute.
*
* @return The processed Object representation of the attribute.
*
* @throws org.xml.sax.SAXException if the attribute value can not be processed.
*/
Object processValue(
StylesheetHandler handler, String uri, String name, String rawName, String value,
ElemTemplateElement owner)
throws org.xml.sax.SAXException
{
int type = getType();
Object processedValue = null;
switch (type)
{
case T_AVT :
processedValue = processAVT(handler, uri, name, rawName, value, owner);
break;
case T_CDATA :
processedValue = processCDATA(handler, uri, name, rawName, value, owner);
break;
case T_CHAR :
processedValue = processCHAR(handler, uri, name, rawName, value, owner);
break;
case T_ENUM :
processedValue = processENUM(handler, uri, name, rawName, value, owner);
break;
case T_EXPR :
processedValue = processEXPR(handler, uri, name, rawName, value, owner);
break;
case T_NMTOKEN :
processedValue = processNMTOKEN(handler, uri, name, rawName, value, owner);
break;
case T_PATTERN :
processedValue = processPATTERN(handler, uri, name, rawName, value, owner);
break;
case T_NUMBER :
processedValue = processNUMBER(handler, uri, name, rawName, value, owner);
break;
case T_QNAME :
processedValue = processQNAME(handler, uri, name, rawName, value, owner);
break;
case T_QNAMES :
processedValue = processQNAMES(handler, uri, name, rawName, value);
break;
case T_QNAMES_RESOLVE_NULL:
processedValue = processQNAMESRNU(handler, uri, name, rawName, value);
break;
case T_SIMPLEPATTERNLIST :
processedValue = processSIMPLEPATTERNLIST(handler, uri, name, rawName,
value, owner);
break;
case T_URL :
processedValue = processURL(handler, uri, name, rawName, value, owner);
break;
case T_YESNO :
processedValue = processYESNO(handler, uri, name, rawName, value);
break;
case T_STRINGLIST :
processedValue = processSTRINGLIST(handler, uri, name, rawName, value);
break;
case T_PREFIX_URLLIST :
processedValue = processPREFIX_URLLIST(handler, uri, name, rawName,
value);
break;
case T_ENUM_OR_PQNAME :
processedValue = processENUM_OR_PQNAME(handler, uri, name, rawName, value, owner);
break;
case T_NCNAME :
processedValue = processNCNAME(handler, uri, name, rawName, value, owner);
break;
case T_AVT_QNAME :
processedValue = processAVT_QNAME(handler, uri, name, rawName, value, owner);
break;
default :
}
return processedValue;
}
/**
* Set the default value of an attribute.
*
* @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
* @param elem The object on which the property will be set.
*
* @throws org.xml.sax.SAXException wraps an invocation exception if the
* setter method can not be invoked on the object.
*/
void setDefAttrValue(StylesheetHandler handler, ElemTemplateElement elem)
throws org.xml.sax.SAXException
{
setAttrValue(handler, this.getNamespace(), this.getName(),
this.getName(), this.getDefault(), elem);
}
/**
* Get the primative type for the class, if there
* is one. If the class is a Double, for instance,
* this will return double.class. If the class is not one
* of the 9 primative types, it will return the same
* class that was passed in.
*
* @param obj The object which will be resolved to a primative class object if possible.
*
* @return The most primative class representation possible for the object, never null.
*/
private Class getPrimativeClass(Object obj)
{
if (obj instanceof XPath)
return XPath.class;
Class cl = obj.getClass();
if (cl == Double.class)
{
cl = double.class;
}
if (cl == Float.class)
{
cl = float.class;
}
else if (cl == Boolean.class)
{
cl = boolean.class;
}
else if (cl == Byte.class)
{
cl = byte.class;
}
else if (cl == Character.class)
{
cl = char.class;
}
else if (cl == Short.class)
{
cl = short.class;
}
else if (cl == Integer.class)
{
cl = int.class;
}
else if (cl == Long.class)
{
cl = long.class;
}
return cl;
}
/**
* StringBuffer containing comma delimited list of valid values for ENUM type.
* Used to build error message.
*/
private StringBuffer getListOfEnums()
{
StringBuffer enumNamesList = new StringBuffer();
String [] enumValues = this.getEnumNames();
for (int i = 0; i < enumValues.length; i++)
{
if (i > 0)
{
enumNamesList.append(' ');
}
enumNamesList.append(enumValues[i]);
}
return enumNamesList;
}
/**
* Set a value on an attribute.
*
* @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
* @param attrUri The Namespace URI of the attribute, or an empty string.
* @param attrLocalName The local name (without prefix), or empty string if not namespace processing.
* @param attrRawName The raw name of the attribute, including possible prefix.
* @param attrValue The attribute's value.
* @param elem The object that should contain a property that represents the attribute.
*
* @throws org.xml.sax.SAXException
*/
boolean setAttrValue(
StylesheetHandler handler, String attrUri, String attrLocalName,
String attrRawName, String attrValue, ElemTemplateElement elem)
throws org.xml.sax.SAXException
{
if(attrRawName.equals("xmlns") || attrRawName.startsWith("xmlns:"))
return true;
String setterString = getSetterMethodName();
// If this is null, then it is a foreign namespace and we
// do not process it.
if (null != setterString)
{
try
{
Method meth;
Object[] args;
if(setterString.equals(S_FOREIGNATTR_SETTER))
{
// workaround for possible crimson bug
if( attrUri==null) attrUri="";
// First try to match with the primative value.
Class sclass = attrUri.getClass();
Class[] argTypes = new Class[]{ sclass, sclass,
sclass, sclass };
meth = elem.getClass().getMethod(setterString, argTypes);
args = new Object[]{ attrUri, attrLocalName,
attrRawName, attrValue };
}
else
{
Object value = processValue(handler, attrUri, attrLocalName,
attrRawName, attrValue, elem);
// If a warning was issued because the value for this attribute was
// invalid, then the value will be null. Just return
if (null == value) return false;
// First try to match with the primative value.
Class[] argTypes = new Class[]{ getPrimativeClass(value) };
try
{
meth = elem.getClass().getMethod(setterString, argTypes);
}
catch (NoSuchMethodException nsme)
{
Class cl = ((Object) value).getClass();
// If this doesn't work, try it with the non-primative value;
argTypes[0] = cl;
meth = elem.getClass().getMethod(setterString, argTypes);
}
args = new Object[]{ value };
}
meth.invoke(elem, args);
}
catch (NoSuchMethodException nsme)
{
if (!setterString.equals(S_FOREIGNATTR_SETTER))
{
handler.error(XSLTErrorResources.ER_FAILED_CALLING_METHOD, new Object[]{setterString}, nsme);//"Failed calling " + setterString + " method!", nsme);
return false;
}
}
catch (IllegalAccessException iae)
{
handler.error(XSLTErrorResources.ER_FAILED_CALLING_METHOD, new Object[]{setterString}, iae);//"Failed calling " + setterString + " method!", iae);
return false;
}
catch (InvocationTargetException nsme)
{
handleError(handler, XSLTErrorResources.WG_ILLEGAL_ATTRIBUTE_VALUE,
new Object[]{ Constants.ATTRNAME_NAME, getName()}, nsme);
return false;
}
}
return true;
}
private void handleError(StylesheetHandler handler, String msg, Object [] args, Exception exc) throws org.xml.sax.SAXException
{
switch (getErrorType())
{
case (FATAL):
case (ERROR):
handler.error(msg, args, exc);
break;
case (WARNING):
handler.warn(msg, args);
default: break;
}
}
}