001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements. See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership. The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the  "License");
007     * you may not use this file except in compliance with the License.
008     * You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    /*
019     * $Id: XSLTAttributeDef.java 468640 2006-10-28 06:53:53Z minchau $
020     */
021    package org.apache.xalan.processor;
022    
023    import java.lang.reflect.InvocationTargetException;
024    import java.lang.reflect.Method;
025    import java.util.StringTokenizer;
026    import java.util.Vector;
027    
028    import javax.xml.transform.TransformerException;
029    
030    import org.apache.xalan.res.XSLMessages;
031    import org.apache.xalan.res.XSLTErrorResources;
032    import org.apache.xalan.templates.AVT;
033    import org.apache.xalan.templates.Constants;
034    import org.apache.xalan.templates.ElemTemplateElement;
035    import org.apache.xml.utils.QName;
036    import org.apache.xml.utils.StringToIntTable;
037    import org.apache.xml.utils.StringVector;
038    import org.apache.xml.utils.XML11Char;
039    import org.apache.xpath.XPath;
040    
041     
042    /**
043     * This class defines an attribute for an element in a XSLT stylesheet,
044     * is meant to reflect the structure defined in http://www.w3.org/TR/xslt#dtd, and the
045     * mapping between Xalan classes and the markup attributes in the element.
046     */
047    public class XSLTAttributeDef
048    {
049       // How to handle invalid values for this attribute 
050       static final int FATAL = 0;
051       static final int ERROR = 1;
052       static final int WARNING = 2;
053       
054       
055      /**
056       * Construct an instance of XSLTAttributeDef.
057       *
058       * @param namespace The Namespace URI, or an empty string.
059       * @param name The local name (without prefix), or empty string if not namespace processing.
060       * @param type One of T_CDATA, T_URL, T_AVT, T_PATTERN, T_EXPR, T_CHAR,
061       * T_NUMBER, T_YESNO, T_QNAME, T_QNAMES, T_ENUM, T_SIMPLEPATTERNLIST,
062       * T_NMTOKEN, T_STRINGLIST, T_PREFIX_URLLIST, T_ENUM_OR_PQNAME, T_NCNAME.
063       * @param required true if this is attribute is required by the XSLT specification.
064       * @param supportsAVT true if this attribute supports AVT's.
065       * @param errorType the type of error to issue if validation fails.  One of FATAL, ERROR, WARNING. 
066       */
067      XSLTAttributeDef(String namespace, String name, int type, boolean required, boolean supportsAVT, int errorType)
068      {
069        this.m_namespace = namespace;
070        this.m_name = name;
071        this.m_type = type;
072        this.m_required = required;
073        this.m_supportsAVT = supportsAVT;
074        this.m_errorType = errorType;
075      }
076    
077      /**
078       * Construct an instance of XSLTAttributeDef.
079       *
080       * @param namespace The Namespace URI, or an empty string.
081       * @param name The local name (without prefix), or empty string if not namespace processing.
082       * @param type One of T_CDATA, T_URL, T_AVT, T_PATTERN, T_EXPR,
083       * T_CHAR, T_NUMBER, T_YESNO, T_QNAME, T_QNAMES, T_ENUM,
084       * T_SIMPLEPATTERNLIST, T_NMTOKEN, T_STRINGLIST, T_PREFIX_URLLIST, 
085       * T_ENUM_OR_PQNAME, T_NCNAME.
086       * @param supportsAVT true if this attribute supports AVT's. 
087       * @param errorType the type of error to issue if validation fails.  One of FATAL, ERROR, WARNING. 
088       * @param defaultVal The default value for this attribute.
089       */
090      XSLTAttributeDef(String namespace, String name, int type, boolean supportsAVT, int errorType, String defaultVal)
091      {
092    
093        this.m_namespace = namespace;
094        this.m_name = name;
095        this.m_type = type;
096        this.m_required = false;
097        this.m_supportsAVT = supportsAVT;  
098        this.m_errorType = errorType;      
099        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    }