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: XSLTAttributeDef.java 468640 2006-10-28 06:53:53Z minchau $
20 */
21package org.apache.xalan.processor;
22
23import java.lang.reflect.InvocationTargetException;
24import java.lang.reflect.Method;
25import java.util.StringTokenizer;
26import java.util.Vector;
27
28import javax.xml.transform.TransformerException;
29
30import org.apache.xalan.res.XSLMessages;
31import org.apache.xalan.res.XSLTErrorResources;
32import org.apache.xalan.templates.AVT;
33import org.apache.xalan.templates.Constants;
34import org.apache.xalan.templates.ElemTemplateElement;
35import org.apache.xml.utils.QName;
36import org.apache.xml.utils.StringToIntTable;
37import org.apache.xml.utils.StringVector;
38import org.apache.xml.utils.XML11Char;
39import org.apache.xpath.XPath;
40
41
42/**
43 * This class defines an attribute for an element in a XSLT stylesheet,
44 * is meant to reflect the structure defined in http://www.w3.org/TR/xslt#dtd, and the
45 * mapping between Xalan classes and the markup attributes in the element.
46 */
47public class XSLTAttributeDef
48{
49   // How to handle invalid values for this attribute
50   static final int FATAL = 0;
51   static final int ERROR = 1;
52   static final int WARNING = 2;
53
54
55  /**
56   * Construct an instance of XSLTAttributeDef.
57   *
58   * @param namespace The Namespace URI, or an empty string.
59   * @param name The local name (without prefix), or empty string if not namespace processing.
60   * @param type One of T_CDATA, T_URL, T_AVT, T_PATTERN, T_EXPR, T_CHAR,
61   * T_NUMBER, T_YESNO, T_QNAME, T_QNAMES, T_ENUM, T_SIMPLEPATTERNLIST,
62   * T_NMTOKEN, T_STRINGLIST, T_PREFIX_URLLIST, T_ENUM_OR_PQNAME, T_NCNAME.
63   * @param required true if this is attribute is required by the XSLT specification.
64   * @param supportsAVT true if this attribute supports AVT's.
65   * @param errorType the type of error to issue if validation fails.  One of FATAL, ERROR, WARNING.
66   */
67  XSLTAttributeDef(String namespace, String name, int type, boolean required, boolean supportsAVT, int errorType)
68  {
69    this.m_namespace = namespace;
70    this.m_name = name;
71    this.m_type = type;
72    this.m_required = required;
73    this.m_supportsAVT = supportsAVT;
74    this.m_errorType = errorType;
75  }
76
77  /**
78   * Construct an instance of XSLTAttributeDef.
79   *
80   * @param namespace The Namespace URI, or an empty string.
81   * @param name The local name (without prefix), or empty string if not namespace processing.
82   * @param type One of T_CDATA, T_URL, T_AVT, T_PATTERN, T_EXPR,
83   * T_CHAR, T_NUMBER, T_YESNO, T_QNAME, T_QNAMES, T_ENUM,
84   * T_SIMPLEPATTERNLIST, T_NMTOKEN, T_STRINGLIST, T_PREFIX_URLLIST,
85   * T_ENUM_OR_PQNAME, T_NCNAME.
86   * @param supportsAVT true if this attribute supports AVT's.
87   * @param errorType the type of error to issue if validation fails.  One of FATAL, ERROR, WARNING.
88   * @param defaultVal The default value for this attribute.
89   */
90  XSLTAttributeDef(String namespace, String name, int type, boolean supportsAVT, int errorType, String defaultVal)
91  {
92
93    this.m_namespace = namespace;
94    this.m_name = name;
95    this.m_type = type;
96    this.m_required = false;
97    this.m_supportsAVT = supportsAVT;
98    this.m_errorType = errorType;
99    this.m_default = defaultVal;
100   }
101
102  /**
103   * Construct an instance of XSLTAttributeDef that uses two
104   * enumerated values.
105   *
106   * @param namespace The Namespace URI, or an empty string.
107   * @param name The local name (without prefix), or empty string if not namespace processing.
108   * @param required true if this attribute is required by the XSLT specification.
109   * @param supportsAVT true if this attribute supports AVT's.
110   * @param prefixedQNameValAllowed If true, the type is T_ENUM_OR_PQNAME
111   * @param errorType the type of error to issue if validation fails.  One of FATAL, ERROR, WARNING.
112   * @param k1 The XSLT name of the enumerated value.
113   * @param v1 An integer representation of k1.
114   * @param k2 The XSLT name of the enumerated value.
115   * @param v2 An integer representation of k2.
116    */
117  XSLTAttributeDef(String namespace, String name, boolean required, boolean supportsAVT,
118                    boolean prefixedQNameValAllowed, int errorType, String k1, int v1, String k2, int v2)
119  {
120
121    this.m_namespace = namespace;
122    this.m_name = name;
123	this.m_type = prefixedQNameValAllowed ? this.T_ENUM_OR_PQNAME : this.T_ENUM;
124    this.m_required = required;
125    this.m_supportsAVT = supportsAVT;
126    this.m_errorType = errorType;
127    m_enums = new StringToIntTable(2);
128
129    m_enums.put(k1, v1);
130    m_enums.put(k2, v2);
131  }
132
133  /**
134   * Construct an instance of XSLTAttributeDef that uses three
135   * enumerated values.
136   *
137   * @param namespace The Namespace URI, or an empty string.
138   * @param name The local name (without prefix), or empty string if not namespace processing.
139   * @param required true if this attribute is required by the XSLT specification.
140   * @param supportsAVT true if this attribute supports AVT's.
141   * @param prefixedQNameValAllowed If true, the type is T_ENUM_OR_PQNAME
142   * @param errorType the type of error to issue if validation fails.  One of FATAL, ERROR, WARNING.    *
143   * @param k1 The XSLT name of the enumerated value.
144   * @param v1 An integer representation of k1.
145   * @param k2 The XSLT name of the enumerated value.
146   * @param v2 An integer representation of k2.
147   * @param k3 The XSLT name of the enumerated value.
148   * @param v3 An integer representation of k3.
149   */
150  XSLTAttributeDef(String namespace, String name, boolean required, boolean supportsAVT,
151                    boolean prefixedQNameValAllowed, int errorType, String k1, int v1, String k2, int v2, String k3, int v3)
152  {
153
154    this.m_namespace = namespace;
155    this.m_name = name;
156	this.m_type = prefixedQNameValAllowed ? this.T_ENUM_OR_PQNAME : this.T_ENUM;
157    this.m_required = required;
158    this.m_supportsAVT = supportsAVT;
159    this.m_errorType = errorType;
160    m_enums = new StringToIntTable(3);
161
162    m_enums.put(k1, v1);
163    m_enums.put(k2, v2);
164    m_enums.put(k3, v3);
165  }
166
167  /**
168   * Construct an instance of XSLTAttributeDef that uses three
169   * enumerated values.
170   *
171   * @param namespace The Namespace URI, or an empty string.
172   * @param name The local name (without prefix), or empty string if not namespace processing.
173   * @param required true if this attribute is required by the XSLT specification.
174   * @param supportsAVT true if this attribute supports AVT's.
175   * @param prefixedQNameValAllowed If true, the type is T_ENUM_OR_PQNAME
176   * @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.
177   * @param v1 An integer representation of k1.
178   * @param k2 The XSLT name of the enumerated value.
179   * @param v2 An integer representation of k2.
180   * @param k3 The XSLT name of the enumerated value.
181   * @param v3 An integer representation of k3.
182   * @param k4 The XSLT name of the enumerated value.
183   * @param v4 An integer representation of k4.
184   */
185  XSLTAttributeDef(String namespace, String name, boolean required, boolean supportsAVT,
186                   boolean prefixedQNameValAllowed, int errorType, String k1, int v1, String k2, int v2,
187                   String k3, int v3, String k4, int v4)
188  {
189
190    this.m_namespace = namespace;
191    this.m_name = name;
192	this.m_type = prefixedQNameValAllowed ? this.T_ENUM_OR_PQNAME : this.T_ENUM;
193    this.m_required = required;
194    this.m_supportsAVT = supportsAVT;
195    this.m_errorType = errorType;
196    m_enums = new StringToIntTable(4);
197
198    m_enums.put(k1, v1);
199    m_enums.put(k2, v2);
200    m_enums.put(k3, v3);
201    m_enums.put(k4, v4);
202  }
203
204  /** Type values that represent XSLT attribute types. */
205  static final int T_CDATA = 1,
206
207  // <!-- Used for the type of an attribute value that is a URI reference.-->
208  T_URL = 2,
209
210  // <!-- Used for the type of an attribute value that is an
211  // attribute value template.-->
212  T_AVT = 3,  // Attribute Value Template
213
214  // <!-- Used for the type of an attribute value that is a pattern.-->
215  T_PATTERN = 4,
216
217  // <!-- Used for the type of an attribute value that is an expression.-->
218  T_EXPR = 5,
219
220  // <!-- Used for the type of an attribute value that consists
221  // of a single character.-->
222  T_CHAR = 6,
223
224  // <!-- Used for the type of an attribute value that is a number. -->
225  T_NUMBER = 7,
226
227  // Used for boolean values
228  T_YESNO = 8,
229
230  // <!-- Used for the type of an attribute value that is a QName; the prefix
231  // gets expanded by the XSLT processor. -->
232  T_QNAME = 9,
233
234  // <!--Used for a whitespace-separated list of QNames where the non-prefixed
235  // entries are not to be placed in the default namespace. -->
236  T_QNAMES = 10,
237
238  // <!-- Used for enumerated values -->
239  T_ENUM = 11,
240
241  // Used for simple match patterns, i.e. xsl:strip-space spec.
242  T_SIMPLEPATTERNLIST = 12,
243
244  // Used for a known token.
245  T_NMTOKEN = 13,
246
247  // Used for a list of white-space delimited strings.
248  T_STRINGLIST = 14,
249
250  // Used for a list of white-space delimited strings.
251  // Prefixes are checked to make sure they refer to
252  // valid namespaces, and are resolved when processed
253  T_PREFIX_URLLIST = 15,
254
255  // Used for enumerated values, one of which could be a qname-but-not-ncname
256  T_ENUM_OR_PQNAME = 16,
257
258  // Used for the type of an attribute value that is a NCName
259  T_NCNAME = 17,
260
261  // Used for QName attributes that are always AVT.  Prefix isn't resolved.
262  T_AVT_QNAME = 18,
263
264  // Used for a list of QNames where non-prefixed items are to be resolved
265  // using the default namespace (This is only true for cdata-section-elements)
266  T_QNAMES_RESOLVE_NULL = 19,
267
268  // Used for a list of white-space delimited strings.
269  // strings are checked to make sure they are valid
270  // prefixes, and are not expanded when processed.
271  T_PREFIXLIST = 20;
272
273  /** Representation for an attribute in a foreign namespace. */
274  static final XSLTAttributeDef m_foreignAttr = new XSLTAttributeDef("*", "*",
275                                            XSLTAttributeDef.T_CDATA,false, false, WARNING);
276
277  /** Method name that objects may implement if they wish to have forein attributes set. */
278  static final String S_FOREIGNATTR_SETTER = "setForeignAttr";
279
280  /**
281   * The allowed namespace for this element.
282   */
283  private String m_namespace;
284
285  /**
286   * Get the allowed namespace for this attribute.
287   *
288   * @return The allowed namespace for this attribute, which may be null, or may be "*".
289   */
290  String getNamespace()
291  {
292    return m_namespace;
293  }
294
295  /**
296   * The name of this element.
297   */
298  private String m_name;
299
300  /**
301   * Get the name of this attribute.
302   *
303   * @return non-null reference to the name of this attribute, which may be "*".
304   */
305  String getName()
306  {
307    return m_name;
308  }
309
310  /**
311   * The type of this attribute value.
312   */
313  private int m_type;
314
315  /**
316   * Get the type of this attribute value.
317   *
318   * @return One of T_CDATA, T_URL, T_AVT, T_PATTERN, T_EXPR, T_CHAR,
319   * T_NUMBER, T_YESNO, T_QNAME, T_QNAMES, T_ENUM, T_SIMPLEPATTERNLIST,
320   * T_NMTOKEN, T_STRINGLIST, T_PREFIX_URLLIST, T_ENUM_OR_PQNAME.
321   */
322  int getType()
323  {
324    return m_type;
325  }
326
327  /**
328   * If this element is of type T_ENUM, this will contain
329   * a map from the attribute string to the Xalan integer
330   * value.
331   */
332  private StringToIntTable m_enums;
333
334  /**
335   * If this element is of type T_ENUM, this will return
336   * a map from the attribute string to the Xalan integer
337   * value.
338   * @param key The XSLT attribute value.
339   *
340   * @return The integer representation of the enumerated value for this attribute.
341   * @throws Throws NullPointerException if m_enums is null.
342   */
343  private int getEnum(String key)
344  {
345    return m_enums.get(key);
346  }
347
348 /**
349   * If this element is of type T_ENUM, this will return
350   * an array of strings - the values in the enumeration
351   *
352   * @return An array of the enumerated values permitted for this attribute.
353   *
354   * @throws Throws NullPointerException if m_enums is null.
355   */
356  private String[] getEnumNames()
357  {
358    return m_enums.keys();
359  }
360
361  /**
362   * The default value for this attribute.
363   */
364  private String m_default;
365
366  /**
367   * Get the default value for this attribute.
368   *
369   * @return The default value for this attribute, or null.
370   */
371  String getDefault()
372  {
373    return m_default;
374  }
375
376  /**
377   * Set the default value for this attribute.
378   *
379   * @param def String representation of the default value for this attribute.
380   */
381  void setDefault(String def)
382  {
383    m_default = def;
384  }
385
386  /**
387   * If true, this is a required attribute.
388   */
389  private boolean m_required;
390
391  /**
392   * Get whether or not this is a required attribute.
393   *
394   * @return true if this is a required attribute.
395   */
396  boolean getRequired()
397  {
398    return m_required;
399  }
400
401  /**
402   * If true, this is attribute supports AVT's.
403   */
404  private boolean m_supportsAVT;
405
406  /**
407   * Get whether or not this attribute supports AVT's.
408   *
409   * @return true if this attribute supports AVT's.
410   */
411  boolean getSupportsAVT()
412  {
413    return m_supportsAVT;
414  }
415
416  int m_errorType = this.WARNING;
417
418  /**
419   * Get the type of error message to use if the attribute value is invalid.
420   *
421   * @return one of XSLAttributeDef.FATAL, XSLAttributeDef.ERROR, XSLAttributeDef.WARNING
422   */
423  int getErrorType()
424  {
425    return m_errorType;
426  }
427  /**
428   * String that should represent the setter method which which
429   * may be used on objects to set a value that represents this attribute
430   */
431  String m_setterString = null;
432
433  /**
434   * Return a string that should represent the setter method.
435   * The setter method name will be created algorithmically the
436   * first time this method is accessed, and then cached for return
437   * by subsequent invocations of this method.
438   *
439   * @return String that should represent the setter method which which
440   * may be used on objects to set a value that represents this attribute,
441   * of null if no setter method should be called.
442   */
443  public String getSetterMethodName()
444  {
445
446    if (null == m_setterString)
447    {
448      if (m_foreignAttr == this)
449      {
450        return S_FOREIGNATTR_SETTER;
451      }
452      else if (m_name.equals("*"))
453      {
454        m_setterString = "addLiteralResultAttribute";
455
456        return m_setterString;
457      }
458
459      StringBuffer outBuf = new StringBuffer();
460
461      outBuf.append("set");
462
463      if ((m_namespace != null)
464              && m_namespace.equals(Constants.S_XMLNAMESPACEURI))
465      {
466        outBuf.append("Xml");
467      }
468
469      int n = m_name.length();
470
471      for (int i = 0; i < n; i++)
472      {
473        char c = m_name.charAt(i);
474
475        if ('-' == c)
476        {
477          i++;
478
479          c = m_name.charAt(i);
480          c = Character.toUpperCase(c);
481        }
482        else if (0 == i)
483        {
484          c = Character.toUpperCase(c);
485        }
486
487        outBuf.append(c);
488      }
489
490      m_setterString = outBuf.toString();
491    }
492
493    return m_setterString;
494  }
495
496  /**
497   * Process an attribute string of type T_AVT into
498   * a AVT value.
499   *
500   * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
501   * @param uri The Namespace URI, or an empty string.
502   * @param name The local name (without prefix), or empty string if not namespace processing.
503   * @param rawName The qualified name (with prefix).
504   * @param value Should be an Attribute Value Template string.
505   *
506   * @return An AVT object that may be used to evaluate the Attribute Value Template.
507   *
508   * @throws org.xml.sax.SAXException which will wrap a
509   * {@link javax.xml.transform.TransformerException}, if there is a syntax error
510   * in the attribute value template string.
511   */
512  AVT processAVT(
513          StylesheetHandler handler, String uri, String name, String rawName, String value,
514          ElemTemplateElement owner)
515            throws org.xml.sax.SAXException
516  {
517
518    try
519    {
520      AVT avt = new AVT(handler, uri, name, rawName, value, owner);
521
522      return avt;
523    }
524    catch (TransformerException te)
525    {
526      throw new org.xml.sax.SAXException(te);
527    }
528  }
529
530  /**
531   * Process an attribute string of type T_CDATA into
532   * a String value.
533   *
534   * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
535   * @param uri The Namespace URI, or an empty string.
536   * @param name The local name (without prefix), or empty string if not namespace processing.
537   * @param rawName The qualified name (with prefix).
538   * @param value non-null string reference.
539   *
540   * @return The value argument.
541   *
542   * @throws org.xml.sax.SAXException.
543   */
544  Object processCDATA(StylesheetHandler handler, String uri, String name,
545                      String rawName, String value, ElemTemplateElement owner)
546                      throws org.xml.sax.SAXException
547  {
548  	if (getSupportsAVT()) {
549	    try
550	    {
551	      AVT avt = new AVT(handler, uri, name, rawName, value, owner);
552	      return avt;
553	    }
554	    catch (TransformerException te)
555	    {
556	      throw new org.xml.sax.SAXException(te);
557	    }
558  	} else {
559	    return value;
560  	}
561  }
562
563  /**
564   * Process an attribute string of type T_CHAR into
565   * a Character value.
566   *
567   * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
568   * @param uri The Namespace URI, or an empty string.
569   * @param name The local name (without prefix), or empty string if not namespace processing.
570   * @param rawName The qualified name (with prefix).
571   * @param value Should be a string with a length of 1.
572   *
573   * @return Character object.
574   *
575   * @throws org.xml.sax.SAXException if the string is not a length of 1.
576   */
577  Object processCHAR(
578          StylesheetHandler handler, String uri, String name, String rawName, String value, ElemTemplateElement owner)
579            throws org.xml.sax.SAXException
580  {
581	if (getSupportsAVT()) {
582	    try
583	    {
584	      AVT avt = new AVT(handler, uri, name, rawName, value, owner);
585
586		  // If an AVT wasn't used, validate the value
587		  if ((avt.isSimple()) && (value.length() != 1)) {
588		  	handleError(handler, XSLTErrorResources.INVALID_TCHAR, new Object[] {name, value},null);
589            return null;
590		  }
591	      return avt;
592	    }
593	    catch (TransformerException te)
594	    {
595	      throw new org.xml.sax.SAXException(te);
596	    }
597	} else {
598	    if (value.length() != 1)
599	    {
600            handleError(handler, XSLTErrorResources.INVALID_TCHAR, new Object[] {name, value},null);
601            return null;
602	    }
603
604	    return new Character(value.charAt(0));
605	}
606  }
607
608  /**
609   * Process an attribute string of type T_ENUM into a int value.
610   *
611   * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
612   * @param uri The Namespace URI, or an empty string.
613   * @param name The local name (without prefix), or empty string if not namespace processing.
614   * @param rawName The qualified name (with prefix).
615   * @param value non-null string that represents an enumerated value that is
616   * valid for this element.
617   * @param owner
618   *
619   * @return An Integer representation of the enumerated value if this attribute does not support
620   *         AVT.  Otherwise, and AVT is returned.
621   */
622  Object processENUM(StylesheetHandler handler, String uri, String name,
623                     String rawName, String value, ElemTemplateElement owner)
624                     throws org.xml.sax.SAXException
625  {
626
627	AVT avt = null;
628	if (getSupportsAVT()) {
629	    try
630	    {
631	      avt = new AVT(handler, uri, name, rawName, value, owner);
632
633	      // If this attribute used an avt, then we can't validate at this time.
634	      if (!avt.isSimple()) return avt;
635	    }
636	    catch (TransformerException te)
637	    {
638	      throw new org.xml.sax.SAXException(te);
639	    }
640	}
641
642    int retVal = this.getEnum(value);
643
644	if (retVal == StringToIntTable.INVALID_KEY)
645    {
646       StringBuffer enumNamesList = getListOfEnums();
647       handleError(handler, XSLTErrorResources.INVALID_ENUM,new Object[]{name, value, enumNamesList.toString() },null);
648       return null;
649    }
650
651	if (getSupportsAVT()) return avt;
652	else return new Integer(retVal);
653
654  }
655
656  /**
657   * Process an attribute string of that is either an enumerated value or a qname-but-not-ncname.
658   * Returns an AVT, if this attribute support AVT; otherwise returns int or qname.
659   *
660   * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
661   * @param uri The Namespace URI, or an empty string.
662   * @param name The local name (without prefix), or empty string if not namespace processing.
663   * @param rawName The qualified name (with prefix).
664   * @param value non-null string that represents an enumerated value that is
665   * valid for this element.
666   * @param owner
667   *
668   * @return AVT if attribute supports AVT. An Integer representation of the enumerated value if
669   *         attribute does not support AVT and an enumerated value was used.  Otherwise a qname
670   *         is returned.
671   */
672  Object processENUM_OR_PQNAME(StylesheetHandler handler, String uri, String name,
673                     String rawName, String value, ElemTemplateElement owner)
674                     throws org.xml.sax.SAXException
675  {
676
677	Object objToReturn = null;
678
679	if (getSupportsAVT()) {
680	    try
681	    {
682	      AVT avt = new AVT(handler, uri, name, rawName, value, owner);
683	      if (!avt.isSimple()) return avt;
684	      else objToReturn = avt;
685	    }
686	    catch (TransformerException te)
687	    {
688	      throw new org.xml.sax.SAXException(te);
689	    }
690	}
691
692    // An avt wasn't used.
693  	int key = this.getEnum(value);
694
695    if (key != StringToIntTable.INVALID_KEY)
696    {
697        if (objToReturn == null) objToReturn = new Integer(key);
698    }
699
700    // enum not used.  Validate qname-but-not-ncname.
701    else
702    {
703        try
704        {
705			QName qname = new QName(value, handler, true);
706            if (objToReturn == null) objToReturn = qname;
707
708			if (qname.getPrefix() == null) {
709	           StringBuffer enumNamesList = getListOfEnums();
710
711 	           enumNamesList.append(" <qname-but-not-ncname>");
712               handleError(handler,XSLTErrorResources.INVALID_ENUM,new Object[]{name, value, enumNamesList.toString() },null);
713               return null;
714
715	        }
716        }
717        catch (IllegalArgumentException ie)
718        {
719           StringBuffer enumNamesList = getListOfEnums();
720           enumNamesList.append(" <qname-but-not-ncname>");
721
722           handleError(handler,XSLTErrorResources.INVALID_ENUM,new Object[]{name, value, enumNamesList.toString() },ie);
723           return null;
724
725        }
726        catch (RuntimeException re)
727        {
728           StringBuffer enumNamesList = getListOfEnums();
729           enumNamesList.append(" <qname-but-not-ncname>");
730
731           handleError(handler,XSLTErrorResources.INVALID_ENUM,new Object[]{name, value, enumNamesList.toString() },re);
732           return null;
733        }
734  	}
735
736  	return objToReturn;
737  }
738
739  /**
740   * Process an attribute string of type T_EXPR into
741   * an XPath value.
742   *
743   * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
744   * @param uri The Namespace URI, or an empty string.
745   * @param name The local name (without prefix), or empty string if not namespace processing.
746   * @param rawName The qualified name (with prefix).
747   * @param value An XSLT expression string.
748   *
749   * @return an XPath object that may be used for evaluation.
750   *
751   * @throws org.xml.sax.SAXException that wraps a
752   * {@link javax.xml.transform.TransformerException} if the expression
753   * string contains a syntax error.
754   */
755  Object processEXPR(
756          StylesheetHandler handler, String uri, String name, String rawName, String value,
757          ElemTemplateElement owner)
758            throws org.xml.sax.SAXException
759  {
760
761    try
762    {
763      XPath expr = handler.createXPath(value, owner);
764
765      return expr;
766    }
767    catch (TransformerException te)
768    {
769      throw new org.xml.sax.SAXException(te);
770    }
771  }
772
773  /**
774   * Process an attribute string of type T_NMTOKEN into
775   * a String value.
776   *
777   * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
778   * @param uri The Namespace URI, or an empty string.
779   * @param name The local name (without prefix), or empty string if not namespace processing.
780   * @param rawName The qualified name (with prefix).
781   * @param value A NMTOKEN string.
782   *
783   * @return the value argument or an AVT if this attribute supports AVTs.
784   *
785   * @throws org.xml.sax.SAXException if the value is not a valid nmtoken
786   */
787  Object processNMTOKEN(StylesheetHandler handler, String uri, String name,
788                        String rawName, String value, ElemTemplateElement owner)
789             throws org.xml.sax.SAXException
790  {
791
792  	if (getSupportsAVT()) {
793	    try
794	    {
795	      AVT avt = new AVT(handler, uri, name, rawName, value, owner);
796
797		  // If an AVT wasn't used, validate the value
798		  if ((avt.isSimple()) && (!XML11Char.isXML11ValidNmtoken(value))) {
799            handleError(handler,XSLTErrorResources.INVALID_NMTOKEN, new Object[] {name,value},null);
800            return null;
801		  }
802	      return avt;
803	    }
804	    catch (TransformerException te)
805	    {
806	      throw new org.xml.sax.SAXException(te);
807	    }
808  	} else {
809  		if (!XML11Char.isXML11ValidNmtoken(value)) {
810            handleError(handler,XSLTErrorResources.INVALID_NMTOKEN, new Object[] {name,value},null);
811            return null;
812  		}
813  	}
814    return value;
815  }
816
817  /**
818   * Process an attribute string of type T_PATTERN into
819   * an XPath match pattern value.
820   *
821   * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
822   * @param uri The Namespace URI, or an empty string.
823   * @param name The local name (without prefix), or empty string if not namespace processing.
824   * @param rawName The qualified name (with prefix).
825   * @param value A match pattern string.
826   *
827   * @return An XPath pattern that may be used to evaluate the XPath.
828   *
829   * @throws org.xml.sax.SAXException that wraps a
830   * {@link javax.xml.transform.TransformerException} if the match pattern
831   * string contains a syntax error.
832   */
833  Object processPATTERN(
834          StylesheetHandler handler, String uri, String name, String rawName, String value,
835          ElemTemplateElement owner)
836            throws org.xml.sax.SAXException
837  {
838
839    try
840    {
841      XPath pattern = handler.createMatchPatternXPath(value, owner);
842
843      return pattern;
844    }
845    catch (TransformerException te)
846    {
847      throw new org.xml.sax.SAXException(te);
848    }
849  }
850
851  /**
852   * Process an attribute string of type T_NUMBER into
853   * a double value.
854   *
855   * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
856   * @param uri The Namespace URI, or an empty string.
857   * @param name The local name (without prefix), or empty string if not namespace processing.
858   * @param rawName The qualified name (with prefix).
859   * @param value A string that can be parsed into a double value.
860   * @param number
861   *
862   * @return A Double object.
863   *
864   * @throws org.xml.sax.SAXException that wraps a
865   * {@link javax.xml.transform.TransformerException}
866   * if the string does not contain a parsable number.
867   */
868  Object processNUMBER(
869          StylesheetHandler handler, String uri, String name, String rawName, String value, ElemTemplateElement owner)
870            throws org.xml.sax.SAXException
871  {
872
873
874	if (getSupportsAVT())
875	{
876		Double val;
877		AVT avt = null;
878	    try
879	    {
880	      avt = new AVT(handler, uri, name, rawName, value, owner);
881
882	      // If this attribute used an avt, then we can't validate at this time.
883	      if (avt.isSimple())
884	      {
885	      	val = Double.valueOf(value);
886	      }
887	    }
888	    catch (TransformerException te)
889	    {
890	      throw new org.xml.sax.SAXException(te);
891	    }
892	    catch (NumberFormatException nfe)
893	    {
894	     	handleError(handler,XSLTErrorResources.INVALID_NUMBER, new Object[] {name, value}, nfe);
895            return null;
896	    }
897	    return avt;
898
899	}
900	else
901    {
902	    try
903	    {
904	      return Double.valueOf(value);
905	    }
906	    catch (NumberFormatException nfe)
907	    {
908            handleError(handler,XSLTErrorResources.INVALID_NUMBER, new Object[] {name, value}, nfe);
909            return null;
910	    }
911    }
912  }
913
914  /**
915   * Process an attribute string of type T_QNAME into a QName value.
916   *
917   * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
918   * @param uri The Namespace URI, or an empty string.
919   * @param name The local name (without prefix), or empty string if not namespace processing.
920   * @param rawName The qualified name (with prefix).
921   * @param value A string that represents a potentially prefix qualified name.
922   * @param owner
923   *
924   * @return A QName object if this attribute does not support AVT's.  Otherwise, an AVT
925   *         is returned.
926   *
927   * @throws org.xml.sax.SAXException if the string contains a prefix that can not be
928   * resolved, or the string contains syntax that is invalid for a qualified name.
929   */
930  Object processQNAME(
931          StylesheetHandler handler, String uri, String name, String rawName, String value, ElemTemplateElement owner)
932            throws org.xml.sax.SAXException
933  {
934
935     try
936        {
937   	      QName qname = new QName(value, handler, true);
938          return qname;
939        }
940        catch (IllegalArgumentException ie)
941        {
942            // thrown by QName constructor
943            handleError(handler,XSLTErrorResources.INVALID_QNAME, new Object[] {name, value},ie);
944            return null;
945        }
946        catch (RuntimeException re) {
947            // thrown by QName constructor
948            handleError(handler,XSLTErrorResources.INVALID_QNAME, new Object[] {name, value},re);
949            return null;
950        }
951  	}
952
953
954  /**
955   * Process an attribute string of type T_QNAME into a QName value.
956   *
957   * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
958   * @param uri The Namespace URI, or an empty string.
959   * @param name The local name (without prefix), or empty string if not namespace processing.
960   * @param rawName The qualified name (with prefix).
961   * @param value A string that represents a potentially prefix qualified name.
962   * @param owner
963   *
964   * @return An AVT is returned.
965   *
966   * @throws org.xml.sax.SAXException if the string contains a prefix that can not be
967   * resolved, or the string contains syntax that is invalid for a qualified name.
968   */
969  Object processAVT_QNAME(
970          StylesheetHandler handler, String uri, String name, String rawName, String value, ElemTemplateElement owner)
971            throws org.xml.sax.SAXException
972  {
973
974       AVT avt = null;
975       try
976       {
977          avt = new AVT(handler, uri, name, rawName, value, owner);
978
979          // If an AVT wasn't used, validate the value
980          if (avt.isSimple())
981          {
982             int indexOfNSSep = value.indexOf(':');
983
984             if (indexOfNSSep >= 0)
985             {
986                  String prefix = value.substring(0, indexOfNSSep);
987                  if (!XML11Char.isXML11ValidNCName(prefix))
988                  {
989                     handleError(handler,XSLTErrorResources.INVALID_QNAME,new Object[]{name,value },null);
990                     return null;
991                  }
992             }
993
994             String localName =  (indexOfNSSep < 0)
995                 ? value : value.substring(indexOfNSSep + 1);
996
997             if ((localName == null) || (localName.length() == 0) ||
998                 (!XML11Char.isXML11ValidNCName(localName)))
999             {
1000                     handleError(handler,XSLTErrorResources.INVALID_QNAME,new Object[]{name,value },null );
1001                     return null;
1002             }
1003          }
1004        }
1005        catch (TransformerException te)
1006        {
1007           // thrown by AVT constructor
1008          throw new org.xml.sax.SAXException(te);
1009        }
1010
1011    return avt;
1012 }
1013
1014  /**
1015   * Process an attribute string of type NCName into a String
1016   *
1017   * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
1018   * @param uri The Namespace URI, or an empty string.
1019   * @param name The local name (without prefix), or empty string if not namespace processing.
1020   * @param rawName The qualified name (with prefix).
1021   * @param value A string that represents a potentially prefix qualified name.
1022   * @param owner
1023   *
1024   * @return A String object if this attribute does not support AVT's.  Otherwise, an AVT
1025   *         is returned.
1026   *
1027   * @throws org.xml.sax.SAXException if the string contains a prefix that can not be
1028   * resolved, or the string contains syntax that is invalid for a NCName.
1029   */
1030  Object processNCNAME(
1031          StylesheetHandler handler, String uri, String name, String rawName, String value, ElemTemplateElement owner)
1032            throws org.xml.sax.SAXException
1033  {
1034
1035    if (getSupportsAVT())
1036    {
1037        AVT avt = null;
1038        try
1039        {
1040          avt = new AVT(handler, uri, name, rawName, value, owner);
1041
1042          // If an AVT wasn't used, validate the value
1043          if ((avt.isSimple()) &&  (!XML11Char.isXML11ValidNCName(value)))
1044          {
1045             handleError(handler,XSLTErrorResources.INVALID_NCNAME,new Object[] {name,value},null);
1046             return null;
1047          }
1048          return avt;
1049        }
1050        catch (TransformerException te)
1051        {
1052           // thrown by AVT constructor
1053          throw new org.xml.sax.SAXException(te);
1054        }
1055
1056    } else {
1057        if (!XML11Char.isXML11ValidNCName(value))
1058        {
1059            handleError(handler,XSLTErrorResources.INVALID_NCNAME,new Object[] {name,value},null);
1060            return null;
1061        }
1062        return value;
1063    }
1064 }
1065
1066  /**
1067   * Process an attribute string of type T_QNAMES into a vector of QNames where
1068   * the specification requires that non-prefixed elements not be placed in a
1069   * namespace.  (See section 2.4 of XSLT 1.0.)
1070   *
1071   * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
1072   * @param uri The Namespace URI, or an empty string.
1073   * @param name The local name (without prefix), or empty string if not namespace processing.
1074   * @param rawName The qualified name (with prefix).
1075   * @param value A whitespace delimited list of qualified names.
1076   *
1077   * @return a Vector of QName objects.
1078   *
1079   * @throws org.xml.sax.SAXException if the one of the qualified name strings
1080   * contains a prefix that can not be
1081   * resolved, or a qualified name contains syntax that is invalid for a qualified name.
1082   */
1083  Vector processQNAMES(
1084          StylesheetHandler handler, String uri, String name, String rawName, String value)
1085            throws org.xml.sax.SAXException
1086  {
1087
1088    StringTokenizer tokenizer = new StringTokenizer(value, " \t\n\r\f");
1089    int nQNames = tokenizer.countTokens();
1090    Vector qnames = new Vector(nQNames);
1091
1092    for (int i = 0; i < nQNames; i++)
1093    {
1094      // Fix from Alexander Rudnev
1095      qnames.addElement(new QName(tokenizer.nextToken(), handler));
1096    }
1097
1098    return qnames;
1099  }
1100
1101 /**
1102   * Process an attribute string of type T_QNAMES_RESOLVE_NULL into a vector
1103   * of QNames where the specification requires non-prefixed elements to be
1104   * placed in the default namespace.  (See section 16 of XSLT 1.0; the
1105   * <em>only</em> time that this will get called is for the
1106   * <code>cdata-section-elements</code> attribute on <code>xsl:output</code>.
1107   *
1108   * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
1109   * @param uri The Namespace URI, or an empty string.
1110   * @param name The local name (without prefix), or empty string if not namespace processing.
1111   * @param rawName The qualified name (with prefix).
1112   * @param value A whitespace delimited list of qualified names.
1113   *
1114   * @return a Vector of QName objects.
1115   *
1116   * @throws org.xml.sax.SAXException if the one of the qualified name strings
1117   * contains a prefix that can not be resolved, or a qualified name contains
1118   * syntax that is invalid for a qualified name.
1119   */
1120  final Vector processQNAMESRNU(StylesheetHandler handler, String uri,
1121    String name, String rawName, String value)
1122    throws org.xml.sax.SAXException
1123  {
1124
1125    StringTokenizer tokenizer = new StringTokenizer(value, " \t\n\r\f");
1126    int nQNames = tokenizer.countTokens();
1127    Vector qnames = new Vector(nQNames);
1128
1129    String defaultURI = handler.getNamespaceForPrefix("");
1130    for (int i = 0; i < nQNames; i++)
1131    {
1132      String tok = tokenizer.nextToken();
1133      if (tok.indexOf(':') == -1) {
1134        qnames.addElement(new QName(defaultURI,tok));
1135      } else {
1136        qnames.addElement(new QName(tok, handler));
1137      }
1138    }
1139    return qnames;
1140  }
1141
1142  /**
1143   * Process an attribute string of type T_SIMPLEPATTERNLIST into
1144   * a vector of XPath match patterns.
1145   *
1146   * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
1147   * @param uri The Namespace URI, or an empty string.
1148   * @param name The local name (without prefix), or empty string if not namespace processing.
1149   * @param rawName The qualified name (with prefix).
1150   * @param value A whitespace delimited list of simple match patterns.
1151   *
1152   * @return A Vector of XPath objects.
1153   *
1154   * @throws org.xml.sax.SAXException that wraps a
1155   * {@link javax.xml.transform.TransformerException} if one of the match pattern
1156   * strings contains a syntax error.
1157   */
1158  Vector processSIMPLEPATTERNLIST(
1159          StylesheetHandler handler, String uri, String name, String rawName, String value,
1160          ElemTemplateElement owner)
1161            throws org.xml.sax.SAXException
1162  {
1163
1164    try
1165    {
1166      StringTokenizer tokenizer = new StringTokenizer(value, " \t\n\r\f");
1167      int nPatterns = tokenizer.countTokens();
1168      Vector patterns = new Vector(nPatterns);
1169
1170      for (int i = 0; i < nPatterns; i++)
1171      {
1172        XPath pattern =
1173          handler.createMatchPatternXPath(tokenizer.nextToken(), owner);
1174
1175        patterns.addElement(pattern);
1176      }
1177
1178      return patterns;
1179    }
1180    catch (TransformerException te)
1181    {
1182      throw new org.xml.sax.SAXException(te);
1183    }
1184  }
1185
1186  /**
1187   * Process an attribute string of type T_STRINGLIST into
1188   * a vector of XPath match patterns.
1189   *
1190   * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
1191   * @param uri The Namespace URI, or an empty string.
1192   * @param name The local name (without prefix), or empty string if not namespace processing.
1193   * @param rawName The qualified name (with prefix).
1194   * @param value a whitespace delimited list of string values.
1195   *
1196   * @return A StringVector of the tokenized strings.
1197   */
1198  StringVector processSTRINGLIST(StylesheetHandler handler, String uri,
1199                                 String name, String rawName, String value)
1200  {
1201
1202    StringTokenizer tokenizer = new StringTokenizer(value, " \t\n\r\f");
1203    int nStrings = tokenizer.countTokens();
1204    StringVector strings = new StringVector(nStrings);
1205
1206    for (int i = 0; i < nStrings; i++)
1207    {
1208      strings.addElement(tokenizer.nextToken());
1209    }
1210
1211    return strings;
1212  }
1213
1214  /**
1215   * Process an attribute string of type T_URLLIST into
1216   * a vector of prefixes that may be resolved to URLs.
1217   *
1218   * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
1219   * @param uri The Namespace URI, or an empty string.
1220   * @param name The local name (without prefix), or empty string if not namespace processing.
1221   * @param rawName The qualified name (with prefix).
1222   * @param value A list of whitespace delimited prefixes.
1223   *
1224   * @return A vector of strings that may be resolved to URLs.
1225   *
1226   * @throws org.xml.sax.SAXException if one of the prefixes can not be resolved.
1227   */
1228  StringVector processPREFIX_URLLIST(
1229          StylesheetHandler handler, String uri, String name, String rawName, String value)
1230            throws org.xml.sax.SAXException
1231  {
1232
1233    StringTokenizer tokenizer = new StringTokenizer(value, " \t\n\r\f");
1234    int nStrings = tokenizer.countTokens();
1235    StringVector strings = new StringVector(nStrings);
1236
1237    for (int i = 0; i < nStrings; i++)
1238    {
1239      String prefix = tokenizer.nextToken();
1240      String url = handler.getNamespaceForPrefix(prefix);
1241
1242      if (url != null)
1243        strings.addElement(url);
1244      else
1245        throw new org.xml.sax.SAXException(XSLMessages.createMessage(XSLTErrorResources.ER_CANT_RESOLVE_NSPREFIX, new Object[] {prefix}));
1246
1247    }
1248
1249    return strings;
1250  }
1251
1252  /**
1253    * Process an attribute string of type T_PREFIXLIST into
1254    * a vector of prefixes that may be resolved to URLs.
1255    *
1256    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
1257    * @param uri The Namespace URI, or an empty string.
1258    * @param name The local name (without prefix), or empty string if not namespace processing.
1259    * @param rawName The qualified name (with prefix).
1260    * @param value A list of whitespace delimited prefixes.
1261    *
1262    * @return A vector of strings that may be resolved to URLs.
1263    *
1264    * @throws org.xml.sax.SAXException if one of the prefixes can not be resolved.
1265    */
1266   StringVector processPREFIX_LIST(
1267           StylesheetHandler handler, String uri, String name,
1268           String rawName, String value) throws org.xml.sax.SAXException
1269   {
1270
1271     StringTokenizer tokenizer = new StringTokenizer(value, " \t\n\r\f");
1272     int nStrings = tokenizer.countTokens();
1273     StringVector strings = new StringVector(nStrings);
1274
1275     for (int i = 0; i < nStrings; i++)
1276     {
1277       String prefix = tokenizer.nextToken();
1278       String url = handler.getNamespaceForPrefix(prefix);
1279       if (prefix.equals(Constants.ATTRVAL_DEFAULT_PREFIX) || url != null)
1280         strings.addElement(prefix);
1281       else
1282         throw new org.xml.sax.SAXException(
1283              XSLMessages.createMessage(
1284                   XSLTErrorResources.ER_CANT_RESOLVE_NSPREFIX,
1285                   new Object[] {prefix}));
1286
1287     }
1288
1289     return strings;
1290   }
1291
1292
1293  /**
1294   * Process an attribute string of type T_URL into
1295   * a URL value.
1296   *
1297   * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
1298   * @param uri The Namespace URI, or an empty string.
1299   * @param name The local name (without prefix), or empty string if not namespace processing.
1300   * @param rawName The qualified name (with prefix).
1301   * @param value non-null string that conforms to the URL syntax.
1302   *
1303   * @return The non-absolutized URL argument, in other words, the value argument.  If this
1304   *         attribute supports AVT, an AVT is returned.
1305   *
1306   * @throws org.xml.sax.SAXException if the URL does not conform to the URL syntax.
1307   */
1308  Object processURL(
1309          StylesheetHandler handler, String uri, String name, String rawName, String value, ElemTemplateElement owner)
1310            throws org.xml.sax.SAXException
1311  {
1312
1313    if (getSupportsAVT()) {
1314	    try
1315	    {
1316	      AVT avt = new AVT(handler, uri, name, rawName, value, owner);
1317
1318		  // If an AVT wasn't used, validate the value
1319		 // if (avt.getSimpleString() != null) {
1320			   // TODO: syntax check URL value.
1321			    // return SystemIDResolver.getAbsoluteURI(value,
1322			    //                                         handler.getBaseIdentifier());
1323		  //}
1324	      return avt;
1325	    }
1326	    catch (TransformerException te)
1327	    {
1328	      throw new org.xml.sax.SAXException(te);
1329	    }
1330     } else {
1331    // TODO: syntax check URL value.
1332    // return SystemIDResolver.getAbsoluteURI(value,
1333    //                                         handler.getBaseIdentifier());
1334
1335	    return value;
1336    }
1337  }
1338
1339  /**
1340   * Process an attribute string of type T_YESNO into
1341   * a Boolean value.
1342   *
1343   * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
1344   * @param uri The Namespace URI, or an empty string.
1345   * @param name The local name (without prefix), or empty string if not namespace processing.
1346   * @param rawName The qualified name (with prefix).
1347   * @param value A string that should be "yes" or "no".
1348   *
1349   * @return Boolean object representation of the value.
1350   *
1351   * @throws org.xml.sax.SAXException
1352   */
1353  private Boolean processYESNO(
1354          StylesheetHandler handler, String uri, String name, String rawName, String value)
1355            throws org.xml.sax.SAXException
1356  {
1357
1358    // Is this already checked somewhere else?  -sb
1359    if (!(value.equals("yes") || value.equals("no")))
1360    {
1361      handleError(handler, XSLTErrorResources.INVALID_BOOLEAN, new Object[] {name,value}, null);
1362      return null;
1363   }
1364
1365     return new Boolean(value.equals("yes") ? true : false);
1366  }
1367
1368  /**
1369   * Process an attribute value.
1370   *
1371   * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
1372   * @param uri The Namespace URI, or an empty string.
1373   * @param name The local name (without prefix), or empty string if not namespace processing.
1374   * @param rawName The qualified name (with prefix).
1375   * @param value The unprocessed string value of the attribute.
1376   *
1377   * @return The processed Object representation of the attribute.
1378   *
1379   * @throws org.xml.sax.SAXException if the attribute value can not be processed.
1380   */
1381  Object processValue(
1382          StylesheetHandler handler, String uri, String name, String rawName, String value,
1383          ElemTemplateElement owner)
1384            throws org.xml.sax.SAXException
1385  {
1386
1387    int type = getType();
1388    Object processedValue = null;
1389
1390    switch (type)
1391    {
1392    case T_AVT :
1393      processedValue = processAVT(handler, uri, name, rawName, value, owner);
1394      break;
1395    case T_CDATA :
1396      processedValue = processCDATA(handler, uri, name, rawName, value, owner);
1397      break;
1398    case T_CHAR :
1399      processedValue = processCHAR(handler, uri, name, rawName, value, owner);
1400      break;
1401    case T_ENUM :
1402      processedValue = processENUM(handler, uri, name, rawName, value, owner);
1403      break;
1404    case T_EXPR :
1405      processedValue = processEXPR(handler, uri, name, rawName, value, owner);
1406      break;
1407    case T_NMTOKEN :
1408      processedValue = processNMTOKEN(handler, uri, name, rawName, value, owner);
1409      break;
1410    case T_PATTERN :
1411      processedValue = processPATTERN(handler, uri, name, rawName, value, owner);
1412      break;
1413    case T_NUMBER :
1414      processedValue = processNUMBER(handler, uri, name, rawName, value, owner);
1415      break;
1416    case T_QNAME :
1417      processedValue = processQNAME(handler, uri, name, rawName, value, owner);
1418      break;
1419    case T_QNAMES :
1420      processedValue = processQNAMES(handler, uri, name, rawName, value);
1421      break;
1422	case T_QNAMES_RESOLVE_NULL:
1423      processedValue = processQNAMESRNU(handler, uri, name, rawName, value);
1424      break;
1425    case T_SIMPLEPATTERNLIST :
1426      processedValue = processSIMPLEPATTERNLIST(handler, uri, name, rawName,
1427                                                value, owner);
1428      break;
1429    case T_URL :
1430      processedValue = processURL(handler, uri, name, rawName, value, owner);
1431      break;
1432    case T_YESNO :
1433      processedValue = processYESNO(handler, uri, name, rawName, value);
1434      break;
1435    case T_STRINGLIST :
1436      processedValue = processSTRINGLIST(handler, uri, name, rawName, value);
1437      break;
1438    case T_PREFIX_URLLIST :
1439      processedValue = processPREFIX_URLLIST(handler, uri, name, rawName,
1440                                             value);
1441      break;
1442    case T_ENUM_OR_PQNAME :
1443    	processedValue = processENUM_OR_PQNAME(handler, uri, name, rawName, value, owner);
1444    	break;
1445    case T_NCNAME :
1446        processedValue = processNCNAME(handler, uri, name, rawName, value, owner);
1447        break;
1448    case T_AVT_QNAME :
1449        processedValue = processAVT_QNAME(handler, uri, name, rawName, value, owner);
1450        break;
1451    case T_PREFIXLIST :
1452      processedValue = processPREFIX_LIST(handler, uri, name, rawName,
1453                                             value);
1454      break;
1455
1456    default :
1457    }
1458
1459    return processedValue;
1460  }
1461
1462  /**
1463   * Set the default value of an attribute.
1464   *
1465   * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
1466   * @param elem The object on which the property will be set.
1467   *
1468   * @throws org.xml.sax.SAXException wraps an invocation exception if the
1469   * setter method can not be invoked on the object.
1470   */
1471  void setDefAttrValue(StylesheetHandler handler, ElemTemplateElement elem)
1472          throws org.xml.sax.SAXException
1473  {
1474    setAttrValue(handler, this.getNamespace(), this.getName(),
1475                 this.getName(), this.getDefault(), elem);
1476  }
1477
1478  /**
1479   * Get the primative type for the class, if there
1480   * is one.  If the class is a Double, for instance,
1481   * this will return double.class.  If the class is not one
1482   * of the 9 primative types, it will return the same
1483   * class that was passed in.
1484   *
1485   * @param obj The object which will be resolved to a primative class object if possible.
1486   *
1487   * @return The most primative class representation possible for the object, never null.
1488   */
1489  private Class getPrimativeClass(Object obj)
1490  {
1491
1492    if (obj instanceof XPath)
1493      return XPath.class;
1494
1495    Class cl = obj.getClass();
1496
1497    if (cl == Double.class)
1498    {
1499      cl = double.class;
1500    }
1501
1502    if (cl == Float.class)
1503    {
1504      cl = float.class;
1505    }
1506    else if (cl == Boolean.class)
1507    {
1508      cl = boolean.class;
1509    }
1510    else if (cl == Byte.class)
1511    {
1512      cl = byte.class;
1513    }
1514    else if (cl == Character.class)
1515    {
1516      cl = char.class;
1517    }
1518    else if (cl == Short.class)
1519    {
1520      cl = short.class;
1521    }
1522    else if (cl == Integer.class)
1523    {
1524      cl = int.class;
1525    }
1526    else if (cl == Long.class)
1527    {
1528      cl = long.class;
1529    }
1530
1531    return cl;
1532  }
1533
1534  /**
1535   * StringBuffer containing comma delimited list of valid values for ENUM type.
1536   * Used to build error message.
1537   */
1538  private StringBuffer getListOfEnums()
1539  {
1540     StringBuffer enumNamesList = new StringBuffer();
1541     String [] enumValues = this.getEnumNames();
1542
1543     for (int i = 0; i < enumValues.length; i++)
1544     {
1545        if (i > 0)
1546        {
1547           enumNamesList.append(' ');
1548        }
1549        enumNamesList.append(enumValues[i]);
1550    }
1551    return enumNamesList;
1552  }
1553
1554  /**
1555   * Set a value on an attribute.
1556   *
1557   * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
1558   * @param attrUri The Namespace URI of the attribute, or an empty string.
1559   * @param attrLocalName The local name (without prefix), or empty string if not namespace processing.
1560   * @param attrRawName The raw name of the attribute, including possible prefix.
1561   * @param attrValue The attribute's value.
1562   * @param elem The object that should contain a property that represents the attribute.
1563   *
1564   * @throws org.xml.sax.SAXException
1565   */
1566  boolean setAttrValue(
1567          StylesheetHandler handler, String attrUri, String attrLocalName,
1568          String attrRawName, String attrValue, ElemTemplateElement elem)
1569            throws org.xml.sax.SAXException
1570  {
1571    if(attrRawName.equals("xmlns") || attrRawName.startsWith("xmlns:"))
1572      return true;
1573
1574    String setterString = getSetterMethodName();
1575
1576    // If this is null, then it is a foreign namespace and we
1577    // do not process it.
1578    if (null != setterString)
1579    {
1580      try
1581      {
1582        Method meth;
1583        Object[] args;
1584
1585        if(setterString.equals(S_FOREIGNATTR_SETTER))
1586        {
1587          // workaround for possible crimson bug
1588          if( attrUri==null) attrUri="";
1589          // First try to match with the primative value.
1590          Class sclass = attrUri.getClass();
1591          Class[] argTypes = new Class[]{ sclass, sclass,
1592                                      sclass, sclass };
1593
1594          meth = elem.getClass().getMethod(setterString, argTypes);
1595
1596          args = new Object[]{ attrUri, attrLocalName,
1597                                      attrRawName, attrValue };
1598        }
1599        else
1600        {
1601          Object value = processValue(handler, attrUri, attrLocalName,
1602                                      attrRawName, attrValue, elem);
1603          // If a warning was issued because the value for this attribute was
1604          // invalid, then the value will be null.  Just return
1605          if (null == value) return false;
1606
1607          // First try to match with the primative value.
1608          Class[] argTypes = new Class[]{ getPrimativeClass(value) };
1609
1610          try
1611          {
1612            meth = elem.getClass().getMethod(setterString, argTypes);
1613          }
1614          catch (NoSuchMethodException nsme)
1615          {
1616            Class cl = ((Object) value).getClass();
1617
1618            // If this doesn't work, try it with the non-primative value;
1619            argTypes[0] = cl;
1620            meth = elem.getClass().getMethod(setterString, argTypes);
1621          }
1622
1623          args = new Object[]{ value };
1624        }
1625
1626        meth.invoke(elem, args);
1627      }
1628      catch (NoSuchMethodException nsme)
1629      {
1630        if (!setterString.equals(S_FOREIGNATTR_SETTER))
1631        {
1632          handler.error(XSLTErrorResources.ER_FAILED_CALLING_METHOD, new Object[]{setterString}, nsme);//"Failed calling " + setterString + " method!", nsme);
1633          return false;
1634        }
1635      }
1636      catch (IllegalAccessException iae)
1637      {
1638        handler.error(XSLTErrorResources.ER_FAILED_CALLING_METHOD, new Object[]{setterString}, iae);//"Failed calling " + setterString + " method!", iae);
1639        return false;
1640      }
1641      catch (InvocationTargetException nsme)
1642      {
1643        handleError(handler, XSLTErrorResources.WG_ILLEGAL_ATTRIBUTE_VALUE,
1644            new Object[]{ Constants.ATTRNAME_NAME, getName()}, nsme);
1645        return false;
1646      }
1647    }
1648
1649    return true;
1650  }
1651
1652  private void handleError(StylesheetHandler handler, String msg, Object [] args, Exception exc) throws org.xml.sax.SAXException
1653  {
1654    switch (getErrorType())
1655    {
1656        case (FATAL):
1657        case (ERROR):
1658                handler.error(msg, args, exc);
1659                break;
1660        case (WARNING):
1661                handler.warn(msg, args);
1662        default: break;
1663    }
1664  }
1665}
1666