KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xalan > templates > OutputProperties


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 /*
17  * $Id: OutputProperties.java,v 1.33 2004/02/16 20:32:32 minchau Exp $
18  */

19 package org.apache.xalan.templates;
20
21 import java.util.Enumeration JavaDoc;
22 import java.util.Properties JavaDoc;
23 import java.util.Vector JavaDoc;
24
25 import javax.xml.transform.OutputKeys JavaDoc;
26 import javax.xml.transform.TransformerException JavaDoc;
27
28 import org.apache.xalan.res.XSLMessages;
29 import org.apache.xalan.res.XSLTErrorResources;
30 import org.apache.xml.serializer.OutputPropertiesFactory;
31 import org.apache.xml.serializer.OutputPropertyUtils;
32 import org.apache.xml.utils.FastStringBuffer;
33 import org.apache.xml.utils.QName;
34
35 /**
36  * This class provides information from xsl:output elements. It is mainly
37  * a wrapper for {@link java.util.Properties}, but can not extend that class
38  * because it must be part of the {@link org.apache.xalan.templates.ElemTemplateElement}
39  * heararchy.
40  * <p>An OutputProperties list can contain another OutputProperties list as
41  * its "defaults"; this second property list is searched if the property key
42  * is not found in the original property list.</p>
43  * @see <a HREF="http://www.w3.org/TR/xslt#dtd">XSLT DTD</a>
44  * @see <a HREF="http://www.w3.org/TR/xslt#output">xsl:output in XSLT Specification</a>
45  *
46  */

47 public class OutputProperties extends ElemTemplateElement
48         implements Cloneable JavaDoc
49 {
50
51   /**
52    * Creates an empty OutputProperties with no default values.
53    */

54   public OutputProperties()
55   {
56     this(org.apache.xml.serializer.Method.XML);
57   }
58
59   /**
60    * Creates an empty OutputProperties with the specified defaults.
61    *
62    * @param defaults the defaults.
63    */

64   public OutputProperties(Properties JavaDoc defaults)
65   {
66     m_properties = new Properties JavaDoc(defaults);
67   }
68
69   /**
70    * Creates an empty OutputProperties with the defaults specified by
71    * a property file. The method argument is used to construct a string of
72    * the form output_[method].properties (for instance, output_html.properties).
73    * The output_xml.properties file is always used as the base.
74    * <p>At the moment, anything other than 'text', 'xml', and 'html', will
75    * use the output_xml.properties file.</p>
76    *
77    * @param method non-null reference to method name.
78    */

79   public OutputProperties(String JavaDoc method)
80   {
81     m_properties = new Properties JavaDoc(
82         OutputPropertiesFactory.getDefaultMethodProperties(method));
83   }
84
85   /**
86    * Clone this OutputProperties, including a clone of the wrapped Properties
87    * reference.
88    *
89    * @return A new OutputProperties reference, mutation of which should not
90    * effect this object.
91    */

92   public Object JavaDoc clone()
93   {
94
95     try
96     {
97       OutputProperties cloned = (OutputProperties) super.clone();
98
99       cloned.m_properties = (Properties JavaDoc) cloned.m_properties.clone();
100
101       return cloned;
102     }
103     catch (CloneNotSupportedException JavaDoc e)
104     {
105       return null;
106     }
107   }
108
109   /**
110    * Set an output property.
111    *
112    * @param key the key to be placed into the property list.
113    * @param value the value corresponding to <tt>key</tt>.
114    * @see javax.xml.transform.OutputKeys
115    */

116   public void setProperty(QName key, String JavaDoc value)
117   {
118     setProperty(key.toNamespacedString(), value);
119   }
120
121   /**
122    * Set an output property.
123    *
124    * @param key the key to be placed into the property list.
125    * @param value the value corresponding to <tt>key</tt>.
126    * @see javax.xml.transform.OutputKeys
127    */

128   public void setProperty(String JavaDoc key, String JavaDoc value)
129   {
130     if(key.equals(OutputKeys.METHOD))
131     {
132       setMethodDefaults(value);
133     }
134     
135     if (key.startsWith(OutputPropertiesFactory.S_BUILTIN_OLD_EXTENSIONS_UNIVERSAL))
136       key = OutputPropertiesFactory.S_BUILTIN_EXTENSIONS_UNIVERSAL
137          + key.substring(OutputPropertiesFactory.S_BUILTIN_OLD_EXTENSIONS_UNIVERSAL_LEN);
138     
139     m_properties.put(key, value);
140   }
141
142   /**
143    * Searches for the property with the specified key in the property list.
144    * If the key is not found in this property list, the default property list,
145    * and its defaults, recursively, are then checked. The method returns
146    * <code>null</code> if the property is not found.
147    *
148    * @param key the property key.
149    * @return the value in this property list with the specified key value.
150    */

151   public String JavaDoc getProperty(QName key)
152   {
153     return m_properties.getProperty(key.toNamespacedString());
154   }
155
156   /**
157    * Searches for the property with the specified key in the property list.
158    * If the key is not found in this property list, the default property list,
159    * and its defaults, recursively, are then checked. The method returns
160    * <code>null</code> if the property is not found.
161    *
162    * @param key the property key.
163    * @return the value in this property list with the specified key value.
164    */

165   public String JavaDoc getProperty(String JavaDoc key)
166   {
167     if (key.startsWith(OutputPropertiesFactory.S_BUILTIN_OLD_EXTENSIONS_UNIVERSAL))
168       key = OutputPropertiesFactory.S_BUILTIN_EXTENSIONS_UNIVERSAL
169         + key.substring(OutputPropertiesFactory.S_BUILTIN_OLD_EXTENSIONS_UNIVERSAL_LEN);
170     return m_properties.getProperty(key);
171   }
172
173   /**
174    * Set an output property.
175    *
176    * @param key the key to be placed into the property list.
177    * @param value the value corresponding to <tt>key</tt>.
178    * @see javax.xml.transform.OutputKeys
179    */

180   public void setBooleanProperty(QName key, boolean value)
181   {
182     m_properties.put(key.toNamespacedString(), value ? "yes" : "no");
183   }
184
185   /**
186    * Set an output property.
187    *
188    * @param key the key to be placed into the property list.
189    * @param value the value corresponding to <tt>key</tt>.
190    * @see javax.xml.transform.OutputKeys
191    */

192   public void setBooleanProperty(String JavaDoc key, boolean value)
193   {
194     m_properties.put(key, value ? "yes" : "no");
195   }
196
197   /**
198    * Searches for the boolean property with the specified key in the property list.
199    * If the key is not found in this property list, the default property list,
200    * and its defaults, recursively, are then checked. The method returns
201    * <code>false</code> if the property is not found, or if the value is other
202    * than "yes".
203    *
204    * @param key the property key.
205    * @return the value in this property list as a boolean value, or false
206    * if null or not "yes".
207    */

208   public boolean getBooleanProperty(QName key)
209   {
210     return getBooleanProperty(key.toNamespacedString());
211   }
212
213   /**
214    * Searches for the boolean property with the specified key in the property list.
215    * If the key is not found in this property list, the default property list,
216    * and its defaults, recursively, are then checked. The method returns
217    * <code>false</code> if the property is not found, or if the value is other
218    * than "yes".
219    *
220    * @param key the property key.
221    * @return the value in this property list as a boolean value, or false
222    * if null or not "yes".
223    */

224   public boolean getBooleanProperty(String JavaDoc key)
225   {
226     return OutputPropertyUtils.getBooleanProperty(key, m_properties);
227   }
228
229   /**
230    * Set an output property.
231    *
232    * @param key the key to be placed into the property list.
233    * @param value the value corresponding to <tt>key</tt>.
234    * @see javax.xml.transform.OutputKeys
235    */

236   public void setIntProperty(QName key, int value)
237   {
238     setIntProperty(key.toNamespacedString(), value);
239   }
240
241   /**
242    * Set an output property.
243    *
244    * @param key the key to be placed into the property list.
245    * @param value the value corresponding to <tt>key</tt>.
246    * @see javax.xml.transform.OutputKeys
247    */

248   public void setIntProperty(String JavaDoc key, int value)
249   {
250     m_properties.put(key, Integer.toString(value));
251   }
252
253   /**
254    * Searches for the int property with the specified key in the property list.
255    * If the key is not found in this property list, the default property list,
256    * and its defaults, recursively, are then checked. The method returns
257    * <code>false</code> if the property is not found, or if the value is other
258    * than "yes".
259    *
260    * @param key the property key.
261    * @return the value in this property list as a int value, or false
262    * if null or not a number.
263    */

264   public int getIntProperty(QName key)
265   {
266     return getIntProperty(key.toNamespacedString());
267   }
268
269   /**
270    * Searches for the int property with the specified key in the property list.
271    * If the key is not found in this property list, the default property list,
272    * and its defaults, recursively, are then checked. The method returns
273    * <code>false</code> if the property is not found, or if the value is other
274    * than "yes".
275    *
276    * @param key the property key.
277    * @return the value in this property list as a int value, or false
278    * if null or not a number.
279    */

280   public int getIntProperty(String JavaDoc key)
281   {
282     return OutputPropertyUtils.getIntProperty(key, m_properties);
283   }
284
285
286   /**
287    * Set an output property with a QName value. The QName will be turned
288    * into a string with the namespace in curly brackets.
289    *
290    * @param key the key to be placed into the property list.
291    * @param value the value corresponding to <tt>key</tt>.
292    * @see javax.xml.transform.OutputKeys
293    */

294   public void setQNameProperty(QName key, QName value)
295   {
296     setQNameProperty(key.toNamespacedString(), value);
297   }
298   
299   /**
300    * Reset the default properties based on the method.
301    *
302    * @param method the method value.
303    * @see javax.xml.transform.OutputKeys
304    */

305   public void setMethodDefaults(String JavaDoc method)
306   {
307         String JavaDoc defaultMethod = m_properties.getProperty(OutputKeys.METHOD);
308  
309         if((null == defaultMethod) || !defaultMethod.equals(method)
310          // bjm - add the next condition as a hack
311
// but it is because both output_xml.properties and
312
// output_unknown.properties have the same method=xml
313
// for their default. Otherwise we end up with
314
// a ToUnknownStream wraping a ToXMLStream even
315
// when the users says method="xml"
316
//
317
|| defaultMethod.equals("xml")
318          )
319         {
320             Properties JavaDoc savedProps = m_properties;
321             Properties JavaDoc newDefaults =
322                 OutputPropertiesFactory.getDefaultMethodProperties(method);
323             m_properties = new Properties JavaDoc(newDefaults);
324             copyFrom(savedProps, false);
325         }
326   }
327   
328
329   /**
330    * Set an output property with a QName value. The QName will be turned
331    * into a string with the namespace in curly brackets.
332    *
333    * @param key the key to be placed into the property list.
334    * @param value the value corresponding to <tt>key</tt>.
335    * @see javax.xml.transform.OutputKeys
336    */

337   public void setQNameProperty(String JavaDoc key, QName value)
338   {
339     setProperty(key, value.toNamespacedString());
340   }
341
342   /**
343    * Searches for the qname property with the specified key in the property list.
344    * If the key is not found in this property list, the default property list,
345    * and its defaults, recursively, are then checked. The method returns
346    * <code>null</code> if the property is not found.
347    *
348    * @param key the property key.
349    * @return the value in this property list as a QName value, or false
350    * if null or not "yes".
351    */

352   public QName getQNameProperty(QName key)
353   {
354     return getQNameProperty(key.toNamespacedString());
355   }
356
357   /**
358    * Searches for the qname property with the specified key in the property list.
359    * If the key is not found in this property list, the default property list,
360    * and its defaults, recursively, are then checked. The method returns
361    * <code>null</code> if the property is not found.
362    *
363    * @param key the property key.
364    * @return the value in this property list as a QName value, or false
365    * if null or not "yes".
366    */

367   public QName getQNameProperty(String JavaDoc key)
368   {
369     return getQNameProperty(key, m_properties);
370   }
371
372   /**
373    * Searches for the qname property with the specified key in the property list.
374    * If the key is not found in this property list, the default property list,
375    * and its defaults, recursively, are then checked. The method returns
376    * <code>null</code> if the property is not found.
377    *
378    * @param key the property key.
379    * @param props the list of properties to search in.
380    * @return the value in this property list as a QName value, or false
381    * if null or not "yes".
382    */

383   public static QName getQNameProperty(String JavaDoc key, Properties JavaDoc props)
384   {
385
386     String JavaDoc s = props.getProperty(key);
387
388     if (null != s)
389       return QName.getQNameFromString(s);
390     else
391       return null;
392   }
393
394   /**
395    * Set an output property with a QName list value. The QNames will be turned
396    * into strings with the namespace in curly brackets.
397    *
398    * @param key the key to be placed into the property list.
399    * @param v non-null list of QNames corresponding to <tt>key</tt>.
400    * @see javax.xml.transform.OutputKeys
401    */

402   public void setQNameProperties(QName key, Vector JavaDoc v)
403   {
404     setQNameProperties(key.toNamespacedString(), v);
405   }
406
407   /**
408    * Set an output property with a QName list value. The QNames will be turned
409    * into strings with the namespace in curly brackets.
410    *
411    * @param key the key to be placed into the property list.
412    * @param v non-null list of QNames corresponding to <tt>key</tt>.
413    * @see javax.xml.transform.OutputKeys
414    */

415   public void setQNameProperties(String JavaDoc key, Vector JavaDoc v)
416   {
417
418     int s = v.size();
419
420     // Just an initial guess at reasonable tuning parameters
421
FastStringBuffer fsb = new FastStringBuffer(9,9);
422
423     for (int i = 0; i < s; i++)
424     {
425       QName qname = (QName) v.elementAt(i);
426
427       fsb.append(qname.toNamespacedString());
428       // Don't append space after last value
429
if (i < s-1)
430         fsb.append(' ');
431     }
432
433     m_properties.put(key, fsb.toString());
434   }
435
436   /**
437    * Searches for the list of qname properties with the specified key in
438    * the property list.
439    * If the key is not found in this property list, the default property list,
440    * and its defaults, recursively, are then checked. The method returns
441    * <code>null</code> if the property is not found.
442    *
443    * @param key the property key.
444    * @return the value in this property list as a vector of QNames, or false
445    * if null or not "yes".
446    */

447   public Vector JavaDoc getQNameProperties(QName key)
448   {
449     return getQNameProperties(key.toNamespacedString());
450   }
451
452   /**
453    * Searches for the list of qname properties with the specified key in
454    * the property list.
455    * If the key is not found in this property list, the default property list,
456    * and its defaults, recursively, are then checked. The method returns
457    * <code>null</code> if the property is not found.
458    *
459    * @param key the property key.
460    * @return the value in this property list as a vector of QNames, or false
461    * if null or not "yes".
462    */

463   public Vector JavaDoc getQNameProperties(String JavaDoc key)
464   {
465     return getQNameProperties(key, m_properties);
466   }
467
468   /**
469    * Searches for the list of qname properties with the specified key in
470    * the property list.
471    * If the key is not found in this property list, the default property list,
472    * and its defaults, recursively, are then checked. The method returns
473    * <code>null</code> if the property is not found.
474    *
475    * @param key the property key.
476    * @param props the list of properties to search in.
477    * @return the value in this property list as a vector of QNames, or false
478    * if null or not "yes".
479    */

480   public static Vector JavaDoc getQNameProperties(String JavaDoc key, Properties JavaDoc props)
481   {
482
483     String JavaDoc s = props.getProperty(key);
484
485     if (null != s)
486     {
487       Vector JavaDoc v = new Vector JavaDoc();
488       int l = s.length();
489       boolean inCurly = false;
490       FastStringBuffer buf = new FastStringBuffer();
491
492       // parse through string, breaking on whitespaces. I do this instead
493
// of a tokenizer so I can track whitespace inside of curly brackets,
494
// which theoretically shouldn't happen if they contain legal URLs.
495
for (int i = 0; i < l; i++)
496       {
497         char c = s.charAt(i);
498
499         if (Character.isWhitespace(c))
500         {
501           if (!inCurly)
502           {
503             if (buf.length() > 0)
504             {
505               QName qname = QName.getQNameFromString(buf.toString());
506               v.addElement(qname);
507               buf.reset();
508             }
509             continue;
510           }
511         }
512         else if ('{' == c)
513           inCurly = true;
514         else if ('}' == c)
515           inCurly = false;
516
517         buf.append(c);
518       }
519
520       if (buf.length() > 0)
521       {
522         QName qname = QName.getQNameFromString(buf.toString());
523         v.addElement(qname);
524         buf.reset();
525       }
526
527       return v;
528     }
529     else
530       return null;
531   }
532
533   /**
534    * This function is called to recompose all of the output format extended elements.
535    *
536    * @param root non-null reference to the stylesheet root object.
537    */

538   public void recompose(StylesheetRoot root)
539     throws TransformerException JavaDoc
540   {
541     root.recomposeOutput(this);
542   }
543
544   /**
545    * This function is called after everything else has been
546    * recomposed, and allows the template to set remaining
547    * values that may be based on some other property that
548    * depends on recomposition.
549    */

550   public void compose(StylesheetRoot sroot) throws TransformerException JavaDoc
551   {
552
553     super.compose(sroot);
554
555   }
556
557   /**
558    * Get the Properties object that this class wraps.
559    *
560    * @return non-null reference to Properties object.
561    */

562   public Properties JavaDoc getProperties()
563   {
564     return m_properties;
565   }
566   
567   /**
568    * Copy the keys and values from the source to this object. This will
569    * not copy the default values. This is meant to be used by going from
570    * a higher precedence object to a lower precedence object, so that if a
571    * key already exists, this method will not reset it.
572    *
573    * @param src non-null reference to the source properties.
574    */

575   public void copyFrom(Properties JavaDoc src)
576   {
577     copyFrom(src, true);
578   }
579
580   /**
581    * Copy the keys and values from the source to this object. This will
582    * not copy the default values. This is meant to be used by going from
583    * a higher precedence object to a lower precedence object, so that if a
584    * key already exists, this method will not reset it.
585    *
586    * @param src non-null reference to the source properties.
587    * @param shouldResetDefaults true if the defaults should be reset based on
588    * the method property.
589    */

590   public void copyFrom(Properties JavaDoc src, boolean shouldResetDefaults)
591   {
592
593     Enumeration JavaDoc keys = src.keys();
594
595     while (keys.hasMoreElements())
596     {
597       String JavaDoc key = (String JavaDoc) keys.nextElement();
598     
599       if (!isLegalPropertyKey(key))
600         throw new IllegalArgumentException JavaDoc(XSLMessages.createMessage(XSLTErrorResources.ER_OUTPUT_PROPERTY_NOT_RECOGNIZED, new Object JavaDoc[]{key})); //"output property not recognized: "
601

602       Object JavaDoc oldValue = m_properties.get(key);
603       if (null == oldValue)
604       {
605         String JavaDoc val = (String JavaDoc) src.get(key);
606         
607         if(shouldResetDefaults && key.equals(OutputKeys.METHOD))
608         {
609           setMethodDefaults(val);
610         }
611
612         m_properties.put(key, val);
613       }
614       else if (key.equals(OutputKeys.CDATA_SECTION_ELEMENTS))
615       {
616         m_properties.put(key, (String JavaDoc) oldValue + " " + (String JavaDoc) src.get(key));
617       }
618     }
619   }
620
621   /**
622    * Copy the keys and values from the source to this object. This will
623    * not copy the default values. This is meant to be used by going from
624    * a higher precedence object to a lower precedence object, so that if a
625    * key already exists, this method will not reset it.
626    *
627    * @param opsrc non-null reference to an OutputProperties.
628    */

629   public void copyFrom(OutputProperties opsrc)
630     throws TransformerException JavaDoc
631   {
632    // Bugzilla 6157: recover from xsl:output statements
633
// checkDuplicates(opsrc);
634
copyFrom(opsrc.getProperties());
635   }
636
637   /**
638    * Report if the key given as an argument is a legal xsl:output key.
639    *
640    * @param key non-null reference to key name.
641    *
642    * @return true if key is legal.
643    */

644   public static boolean isLegalPropertyKey(String JavaDoc key)
645   {
646
647     return (key.equals(OutputKeys.CDATA_SECTION_ELEMENTS)
648             || key.equals(OutputKeys.DOCTYPE_PUBLIC)
649             || key.equals(OutputKeys.DOCTYPE_SYSTEM)
650             || key.equals(OutputKeys.ENCODING)
651             || key.equals(OutputKeys.INDENT)
652             || key.equals(OutputKeys.MEDIA_TYPE)
653             || key.equals(OutputKeys.METHOD)
654             || key.equals(OutputKeys.OMIT_XML_DECLARATION)
655             || key.equals(OutputKeys.STANDALONE)
656             || key.equals(OutputKeys.VERSION)
657             || (key.length() > 0)
658                   && (key.charAt(0) == '{')
659                   && (key.lastIndexOf('{') == 0)
660                   && (key.indexOf('}') > 0)
661                   && (key.lastIndexOf('}') == key.indexOf('}')));
662   }
663
664   /** The output properties.
665    * @serial */

666   private Properties JavaDoc m_properties = null;
667
668     /**
669      * Creates an empty OutputProperties with the defaults specified by
670      * a property file. The method argument is used to construct a string of
671      * the form output_[method].properties (for instance, output_html.properties).
672      * The output_xml.properties file is always used as the base.
673      * <p>At the moment, anything other than 'text', 'xml', and 'html', will
674      * use the output_xml.properties file.</p>
675      *
676      * @param method non-null reference to method name.
677      *
678      * @return Properties object that holds the defaults for the given method.
679      *
680      * @deprecated Use org.apache.xml.serializer.OuputPropertiesFactory.
681      * getDefaultMethodProperties directly.
682      */

683     static public Properties JavaDoc getDefaultMethodProperties(String JavaDoc method)
684     {
685         return org.apache.xml.serializer.OutputPropertiesFactory.getDefaultMethodProperties(method);
686     }
687 }
688
Popular Tags